Free Shipping on Canadian Orders over $150!

News

February 20, 2019

0 comments

Posted in


Driving a Mechanical Speedometer with a Raspberry Pi Part 2 of 2: The Code and Electrical Bits

In our first installment, you learned how we put together our Raspberry Pi-powered Mechanical Speedometer, now we will share how the device works.

First, a bit about the Adafruit Motor HAT.  This is a great add-on board for the Pi, and it allows you to control up to 4 regular motors.  You have to solder the headers to the HAT which takes a few minutes.  The HAT should be powered separate from the Pi, and the HAT can take 5V to 12V.  The HAT does not have a barrel jack connector, but you can use an adapter and some wire.   In our case, we ran the HAT at 5V because our Beefy Hobby Motor drove the speedometer quite well with 5V.  

In classic Adafruit fashion, they have an excellent tutorial for the Motor HAT, as well as an easy to use Python library.  The library is in Python 3, and you install it with the following command: 

sudo pip3 install adafruit-circuitpython-motorkit

Now we'll step you through our code.

First, we import all the libraries we need:

  • "json" is the Javascript Object Notation library, and it is how Shopify's API formats its data.  
  • "requests" is how we do an HTTPS request to Shopify's API
  • "time" allows us to put in a "sleep" message, telling the code to pause
  • "sqlite3" is the library for our SQL database of orders
  • "MotorKit" is the library we imported earlier that controls the Adafruit Motor HAT
import json, requests, time, sqlite3
from adafruit_motorkit import MotorKit
We define the function we will use to drive the motor:

kit = MotorKit()

We like using databases to handle data in any setting, so we are using a database to track the orders on our Odometer Pi.  This simple database tracks the orders numbers, so we know when a new order has arrived.  We create a database if it does not exist, keeping the order number as a unique integer.  We then select the largest order number from the database, which we will use later on when we compare to the "new" largest order number.

cur.execute('''
CREATE TABLE IF NOT EXISTS Orders (
order_num INT UNIQUE,
order_num_str TEXT
)
''')

cur.execute('SELECT MAX(order_num) FROM Orders')
order_max_list = cur.fetchone()
start_max_order = order_max_list[0]

Here we are establishing input_orders as the URL we'll use to obtain the JSON file of our latest orders.  Replace your_api_key and "your_store" as appropriate.  We then create a request with the URL and parse the JSON data with r.json()

input_orders = "https://your_api_key@your_store.myshopify.com/admin/orders.json?limit=250"

r = requests.get(input_orders)

data_orders = r.json()

In this block of code we are pulling useful information out of the JSON file.  In the world of Shopify, the order number is a string called "name", so we have to parse out the numeric portion.  We then insert the new orders into the database, if applicable.  With the "INSERT OR IGNORE" statement, it will only insert new data if the latest order number is different from all the other order numbers, since order_number is a "unique" item in our database schema.

for item_order in data_orders["orders"]:


this_order_str = item_order["name"]
this_order_number = int(this_order_str[1:6])
cur.execute('''INSERT OR IGNORE INTO Orders (order_num, order_num_str) VALUES ( ?, ?)''', (this_order_number, this_order_str))
conn.commit()

After we have updated the  the database with any new entries, we do another check of the database to get the largest number:

cur.execute('SELECT MAX(order_num) FROM Orders')
order_max_list = cur.fetchone()
end_max_order = order_max_list[0] 

In this block of code, we are checking the "ending max order" against the "starting max order".  If the ending number is greater, we calculate how many new orders with the variable "increment".  We then print to the screen that we are incrementing the odometer.

Through trial and error, we have determined that running the motor 10.5 seconds at 100% throttle will increase the odometer by 0.1 miles, or for us, 1 order.  So we run the motor at 100%, pause code execution for 10.5 seconds with time.sleep, and then turn off the motor.

If no new orders came in, we print a message to the console.

if (end_max_order > start_max_order):


increment = (end_max_order - start_max_order)
print ("Incrementing odometer by: ", increment)
runtime = increment * 10.5
kit.motor1.throttle = 1
time.sleep(runtime)
kit.motor1.throttle = 0
else:
print ("Nothing to report, last order E" + str(end_max_order))

For our program to run automatically, we add it as a Cron job.  To do this, we edit our crontab with the following command:

  • crontab -e

We then add the following line to our crontab, which causes our script to run every 2 minutes and then appends the text output to a log file.  

*/2 * * * * python3 /home/pi/odo_order.py >> /home/pi/cron.log 2>&1

This was a super fun project for me, as it combines an old mechanical part with my favourite single board computer, the Raspberry Pi.  If you are interested in learning Python, I highly recommend Dr. Charles Severance's excellent Python for Everybody Specialization from the University of Michigan via Coursera.  I personally did the entire specialization, and it has been priceless as we have built a bunch of Python scripts to help run our business.

Finally, here is the end result in action:

And here's what happens when we get an order, now shipping order 9366:

February 20, 2019

0 comments

Posted in


Driving a Mechanical Speedometer with a Raspberry Pi Part 1 of 2: The Mechanical Bits

Mechanical things are so satisfying.  We love taking an old piece of equipment and making it work with products we sell.

Back in the day, speedometers were driven by spinning cables.  These cables would typically run from the transmission via a flexible steel cable in a sheath to the speedometer.  Ever been in an older car where the speedometer bounces?  That is usually because the speedometer cable is about to fail.

We have been looking for interesting ways to represent data, and we were thinking it would be fun to use an old odometer to show how many orders we have received.  To do this, we would need an old speedometer/odometer assembly, a motor, a way to drive the motor, and a way to couple the motor to the speedometer.

We found an old speedometer on Kijiji for $10 and verified that the odometer worked.  The odometer came with 1/10 of a mile on it!  We believe it came off an exercise bike...which must have collected a lot of dust!  On the back of the speedometer, there is an input shaft with a square hole in it.  To drive the speedometer, you just spin the input shaft.  To test a speedometer, you can use a drill.

 

 

Now we had to find a way to drive the speedometer.  It turns out that our Beefy Hobby Motors work really well for this application.  At first we just took the input shaft and wrapped some tape around it.  This sort of worked, but it was clear we would need something better, as there was a lot of slippage.  We needed this thing to be precise!

Fortunately, we were able to find a speedometer cable repair kit on Amazon!  With this, we got the cable with a square end on it.  We were able to cut the cable with heavy duty wire cutters and put one end of it into a shaft coupler.  The coupler attached to our Beefy Hobby Motor, and the other end of the cable went into the speedometer.

Everything worked great, but we needed a project enclosure.  Since we have a thing for laser cut boxes, we made a 78x78x70mm box out of 3mm birch plywood and added cutouts for the speedometer, motor, and a mounting point for a Raspberry Pi.   As always, we used MakerCase to lay out the case, and then added in the required holes via Inkscape.  

Here are some pictures showing the box layout and the parts.  In the layout, the piece floating in the lower left is the removable top.

And here are some pictures of the finished device:

 

Next, check out Part 2 of this blog post!

February 15, 2019

0 comments

Posted in


New 2019 Products Roundup

We've added a section to the website to feature all the new products in stock.

Here's an overview of all the exciting new options. 

eInk Hats 

  • Inky What     4.2"  (400x300 pixels) for Raspberry Pi  (any 40 pin)
  • PaPiRus Zero for Raspberry Pi Zero

  

 

Arduino

Two new on board WiFi options from Arduino Foundation !

  

 

 

Micro:Bit

 

    

 

  

 

SparkFun

 ProtoSnap uses Alligator clips to easily connect components to Micro:Bit. 

     

Pimoroni

 

 

 

New Vendors !

Monk Makes

 

 .  . 

 

OpenMV

 

PiSupply

 

WittyPi

      

December 20, 2018

0 comments

Posted in


Good Foot Delivery

We are please to now offer Good Foot courier service within Toronto area.  

Good Foot is a courier service that helps provide meaningful work to people with development disabilities.  Their prices are reasonable and the service is excellent.  We did a recent delivery to the King and University area, and our cost was $20+ HST.  The courier picked up the order at 1:00 and delivered it by 4:30.

Right now we do not have a way to quote Good Foot service online, but if you are in Toronto, relatively close to the TTC, and you need your order today, give us a call at 437-886-5274 and we can setup the order for you over the phone!  Please note that same day service only applies to order placed by 1:00.

December 20, 2018

0 comments

Posted in microbit, xmas


Micro:Bit 2 player Christmas Messenger

Merry Christmas from Elmwood !

Here's a very silly two player game for two Micro:Bits to message each other holiday icons. 

You can

Press A to send a Christmas Tree with a blinking light.

Press B to send a Grinch Face. 

Press A + B to send a heart.  

Or

Shake the Micro:Bit to send a hug. 

To the other Micro:Bit !

You can use this to make a Rock Paper Scissors type guessing game, or make up your own rules ! 

 

Both Micro:Bits will need to have the same HEX file on them

Enjoy !

December 10, 2018

0 comments

Posted in


Christmas 2018 shipping guidelines

Hard to believe, but Christmas is only 2 weeks away!

Here are some guidelines to make sure your orders get to you in time for Christmas

  • Check out the below example showing actual rates for a package shipping to Vancouver from Toronto.  Notice that some of the options show how many business days to expect for shipping.  This is very important to factor.  Note that the number of days does not necessarily constitute a guarantee.  To be safe, you'll probably want to add 1 business day in your calculations.
  • Do not select "Small and Light" and have any expectation of getting it for Christmas.  You might get it, you might not, we have zero control over it.
  • UPS is picking up from us super early these days.  So get your order in no later than 11:00 AM Eastern time for it to go out the same day, assuming everything is in stock.  Canada Post continues to pickup later in the day, so orders placed by 3:00 PM will go out that day.
  • Pre-Order items are taking longer than usual to get to us, count on 7 to 10 days.  If you really need something fast, contact us via email and we will see if we can get it quicker.
  • Lastly, if you are worried about shipping, you can always pickup an Elmwood Electronics Gift Card!

December 10, 2018

0 comments

Posted in cam m7, camera, openMV


OpenMV Cam M7 first look

Initial setup guide & feature exploration for the OpenMV Cam M7

{ Will refer to the 'OpenMV Cam M7' as 'OMVC' from now on. }

Things you will need to start...

- OpenMV Cam M7
- microUSB to USB (normal) cable
- Male to Male pin Jumper wire
- MicroSD-Card 16gig or  32 gig

Go to OpenMV.io and download the installer.
Testing done on Windows*

Install it. I know, not ANOTHER IDE, but this one is actually useful.

The OMVC documentation and tutorials are a locally installed website. This is something I am always happy about as inevitably I will be somewhere without wifi & need detailed pinout information. Eg. in a field setting up a remote motion capture wildlife photography rig, something the OMVC is a perfect device for. Offline documentation is also crucial if you like to periodically disconnect from the internet for productivity / sanity reasons.

First boot

THE DEVICE.
Accept all the windows device driver pop-ups.

The OMVC internal memory (like Adafruit circuit python devices) will mount as an external usb drive. If you double click to open it, you can see the Main.py file on the internal board memory.

It is a good idea to read over the documentation to grasp the ways in which it operates as a usb flash drive. It's slightly different than your common expectations.

I've summarized some of the key points : 

  • OMVC only works with FAT.
  • Max readable SDHC card value is 32 gigs  
  • If the camera saves a picture to the SD Card while mounted on a pc... the PC won't see the photo without remounting the drive as it assumes USB flash drives can't magically create files on their own (which is usually true 99% of the time).


3 ways OMVC will mount as a USB device :

  1. Only internal on board memory (no SD Card) :  2 Megs
    Will appear as a standard USB drive.
    Contents will be 'Main.py' 

  2. With MicroSD card inserted on board :
    To capture any images or video you have to insert a microSD card.
    You won't get a warning until the runtime file tries to save a file.
    This will now supplant the internal memory and be the default usb drive you see.
    When you plug in the OMVC, you will ***no longer see the internal 2 Meg memory*** mounted to the desktop. 
    Only the Camera SD Card will now mount to desktop. 

  3. DF Firmware update
    Should only appear when two specific jumper pins are shorted.
    Very similar to updating the firmware on an Adafruit GemmaM0 or CircuitPythonExpress.
    This isn't a drive you would write anything to directly. 


Now we've got that out of the way, let's launch the OpenMV IDE !

It will likely immediately ask you to update the firmware by shorting the BOOT / Reset pins on the device with a (male-male) jumper wire.



I held the jumpers on an angle to ensure contact, if you were going to be a perfectionist, using a dual headed pogo pin adapter would be a better idea.

Follow the prompts & make sure you have a handhold you can maintain for a few minutes.



The device will need to be unplugged and plugged back in again.

When dealing with micro-circuitry, I always remove the USB cable to the computer and LEAVE the device-end inserted at all times to reduce wear and tear on the delicate board joints.

The blue LED will now flash as the firmware is updated. I didn't time it exactly, but it felt like about 30mins to re-flash the firmware. Results may vary with USB 3.0, I used a 2.0 port.

Once that is all set, you can now open the IDE and open 'helloworld_1.py' from the Example files.

Click Connect at the bottom left

The play arrow will now turn green. Click it. 

You will see the camera display on the top right of the IDE.


If not, click the arrow on the middle far right to expand the live preview & color histogram (Red Green Blue channel values).  

Let's have a look at some of the examples. 



I really have to emphasize how important reading the #comments are for each example file.

For decent results with recognition, you need good consistent lighting.

These photos are mostly screen capped from the IDE in Windows and enlarged < ENHANCE ! >, THEN compressed for the blog, so don't consider these perfect examples of the camera capture quality.


First Run Camera Tests


Vector Overlay Drawing

You can manually code vector shapes to be overlaid on the camera images.
The OMVC system uses this capability to demarcate objects as we will see in the photos below. This demo draws circles over the camera input. 



Shape Recognition

Meet our test suite objects !
A square glass coaster, a white iPhone 4S and a green hair elastic. 



Circle Detection

Hair Elastic

I think I compromised the hair elastic test with the heavy shadow casting lighting. 
It correctly identified the camera circle on the iPhone. 
The home button was too small of a color difference to detect. 


Rect(angle) Detection

This feature is amazing and the most rock solid thing I tested.
Super cool.


Real time Edge Detection

My hand over thinkpad keyboard



White iPhone4S on white table (the UNFAIR test). 

White iPhone4S on dark blue background (FAIR test) 

Self Reflection Test
(Reflection of itself on screen of white iPhone4S on dark blue background)


Thankfully, It did not recognize it's own reflection, or demonstrate any other signs of self awareness, so we are safe for now.

HOWEVER it does have the capability to learn to recognize things, utilizing python machine learning, so that might be a fun future experiment.

 

Facial Recognition 

Facial detection works surprisingly well in properly lit conditions.

The default example file was able to identify two faces with different skin colors moving slowly in the same frame at the same time. You do need to have both eyes facing the camera, but there were surprisingly low false positives.

Facial recognition doesn't do as well in poor lighting. One could tweak the code tolerance values, but for low light uses, the optional Infra-Red lens would make more sense. This blog is more of a cursory run through the example files.


Conclusion 


Barely scratched the surface of this exciting new platform and already very impressed. This is the best option if you want to learn camera based programming.

According to the documentation, the IDE previews camera frame rates at about half the capture speed. SDCard recording is at full frame-rate. Perceptually, I didn't notice any frame-rate loss on my laptop.

If you want to look at the python example files directly, the Examples are buried here in windows (will very based on OS):
C:\Program Files\OpenMV IDE\share\qtcreator\examples

One more bonus to using micro-python vs. C is the next time you plug in your M7 board (without the sd card inserted), you can open & read the .py file to remember what program the camera is running.

This is a huge improvement over the more traditional Arduino approach where you can't easily read the sketch that was previously written to the board.

 The M7 captures at 640x480 but depending on the use-case scenarios sometimes what looked like 320x240 greyscale to maintain real time recognition performance for barcode or facial recognition. I'll have to dig into the documentation and do further testing before I can confirm that.


The only things close to this at the moment would be either 


In further blogs, I will be exploring the various shields the OMVC can interact with (LCD, wifi, etc.).

To further explain one point, micro-python is a smaller, reduced function subset of the desktop and server language Python. Micro-Python is made specifically for single board circuitry devices.

The OMVC device works with Micro-Python, not normal Python, so installing desktop python should be redundant as OpenMV IDE should install all you need.

However, if you have NO standard Python on your system already, and at some point later on you want to learn more standard Python to improve your micro-python skill-set, it is generally recommended to go with the latest version (3.4 as of this blog).

1 2 3 10 Next »