With a fancy-pants, standalone, OLED-equipped, high-zoot test jig, of course.
At least, that's what I built for testing my eeZee MicroSD boards. They're microSD breakouts for breadboard Arduinos. They've got the microSD socket plus 3.3V regulator, level-shifter IC, and various passives.
The test jig features an Arduino on the top of a two-layer permanent breadboard apparatus. Power is supplied by convenient USB connector. I manually place the board onto good ol' pogo pins soldered into the D10-D13 positions (plus power and ground).
A red and a green LED indicates overall status, while the Digole Serial OLED displays pass/fail status for each of the tests: initializing the card, creating a file, and removing a file, with an overall board status.
The test takes just a few hundred milliseconds to complete. The test jig is ready to go at any time. Just plug in a USB cable for power I can run through dozens of boards in a few minutes.
Look through the output for open() syscalls like this one.
open("/usr/local/lib/libudev.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
The problem is that redlinkserv cannot find libudev.so.1 because the 32-bit version of libudev is named something different on your distro. (I'm using Mint 13, for example). First, you have to find the i386 library. Use find to search for the file. Specify -type f to ignore softlinks. Search in /lib, /usr/lib (try other directories if you don't find it in these):
$ find -type f /lib /usr/lib -name 'libudev.so.*' -type f
If you don't find it, you'll need to install it (apt-get install libudev0 or equivalent)
You want the 32-bit version. Use ls to find out which is a valid link/file. Then soft link to this from /usr/local/lib:
One of our backers, Damage, had a great project idea for OpenMV Cam: count a dice roll visually. Here's what I ended up with.
I used simple blob detection. What ended up working best was to first find the white dice (I had no real dice; these are paper cutouts).
To look for color blobs you supply the threshold() function with a color, an RGB value, and a "distance" value (how close a pixel is to the specified color). Behind the scenes this is based on LAB colorspace and euclidean distance between colors.
bin = image.threshold([(160, 210, 255)], 20)
The dice are actually blueish-white. I run the blob detection example, then stop it. Then move the mouse over the dice in a few areas and make a note of the approximate RGB values. Then I tweak the RGB values and distance until I'm fairly accurately detecting only the white dice.
Note the dice are actually bluish-white
To filter out any missing pixels, merge the nearby detected ones by calling dilate() then erode() with pixel size parameters.
# image closing bin.dilate(5) bin.erode(2)
Then call find_blobs() on the binary image and it'll return a list of (x, y, color-index) tuples. If you are trying to match multiple colors, the color-index tells you which color the blob matches. Putting it all together, this is the code for finding blue-white blobs:
# Find white dice dbin = image.threshold([(160, 210, 255)], 20) # image closing dbin.dilate(5) dbin.erode(2) # find dice dice = dbin.find_blobs() # Draw rectangles around detected dice for d in dice: image.draw_rectangle(d[0:4])
Now to find the pips. Same process all over again, only this time, the color is sort of a bluish black. I had to experiment with the color and the dilate/erode calls to get it working.
Finally, go through all the pips and count the ones that are inside the bounds of the white blobs, the dice. Then display the numbers in the corners of the dice and the total at the bottom. The find_blobs() function returns a list of (x, y, width, height) for each blob.
# Count pips pips = 0 for d in dice: dr = (d, d, d+d, d+d) subpips = 0 for p in blobs: pr = (p, p, p+p, p+p) if pr > dr and pr < dr and pr > dr and pr < dr: subpips += 1 image.draw_rectangle(p[0:4]) image.draw_string(d-8, d-8, str(subpips), (50, 255, 50)) pips += subpips image.draw_string(55, 120, "total="+str(pips), (50, 255, 50))
And that's all there is. It works pretty ok for having spent very little time on it. There's some room for improvement. More tuning might help. Better lighting. Real dice. Also, when you roll a 6, it merges adjacent pips.
That's because the firmware normally ignores blobs that are too small. Small blobs next to each other can only be detected if you dilate() enough to make them bigger than the threshold, but that merges them because they're close together. We just have to lower the blob size threshold, I think.
Also, we might get more accurate detection by refactoring threshold() to take separate parameters for color and lightness thresholds.
Meanwhile, OpenMV Cam's Kickstarter ends Feb 25. If you want one click here.
OpenMV Cam, 1.8" x 1.4", final week on Kickstarter
If you haven't heard of OpenMV Cam, it's a small machine vision module that's affordable, and the first that runs Python and is expandable with shields. It's funded and we're entering our final week on Kickstarter so don't miss out.
Wait. Python? Yes, it runs Micro Python on the module.
For NoCo Mini-Maker Faire, I set up a demo with my red Magician robot rotating to track a yellow object (placed on my Pololu 3pi). I tweaked the color tracking script in a few minutes to output the blob coordinates over serial to the PIPduino controlling the Magician, then wrote the Arduino code in another few minutes to spin in place based on blob position. Then tuned the color matching, et voila:
As for shields, we now have a thermopile array sensor shield available. We're working on a WiFi shield, LCD Shield, and a few others for later release.
IR / Thermopile bundle: OpenMV Cam plus IR lens, thermopile shield, USB
With the thermopile shield, based on a 16x4 Melexis MLX90620 sensor, you write a simple python script to overlay a heat map on the camera image as in this demo video (we used an LCD prototype shield here, but you get the idea):
So if you want to join our community, and get yourself an OpenMV Cam at Kickstarter pricing, here's the link to make a pledge: http://bit.ly/OMVKS - we appreciate any support you can offer, thanks!
I used a Sparkfun coupon to buy a couple of vintage, 4-digit, 7-segment, HP LED bubble displays. The kind you'd find in really old calculators. Their guide is most helpful.
I used one of my spare eeZee Propellers to play around with the display and create driver code. I haven't played in Spin in awhile, so it was a good refresher. Here's what I did...
The LED module uses four cathodes, one for each digit, and common anodes for the 7 segments. The underside of the LED has a little dot to indicate pin 1. The rest of the pinout tips you can find in the image below.
Since you want no more than 5mA running through these LEDs, I calculated that a 1K resistor would be about right. At 3.3V, with 1.6V forward drop, that's about 2mA, max.
Propeller pins P16 - P19 are connected to Cathode 4 through 1, respectively. Pins P20 - P26 are connected to Anode A through G, respectively. The decimal point is hooked up to P27.
Driving 7-Segment Displays
So, how do you drive one of these displays? To turn on an LED segment its anode must be high, and cathode low. These HP bubble displays are common-anode, meaning there's a unique cathode for each display digit, but each anode is shared across all the display digits.
You could simply drive the display one digit at a time, setting all the required anodes high and the corresponding cathode low.
The problem is, each digit requires a different number of LED segments. Compare 1, which requires 2 LED segments, with 8 which requires 6 segments. If you used a resistor per cathode, 1 would look brightest and 8 would appear dimmest.
A common cathode display is intended to be controlled with the cathodes. Use 4 resistors, one for each cathode, power each of the common anodes sequentially, and use the cathodes to individually turn segments on or off for each display digit position.
The display driver runs on a cog and displays digits stored in hub memory. The main cog simply counts from 0 to 9999 over and over again, extracting the 1's, 10's, 100's and 1000's place and storing the numbers for display, as follows, where b1, b2, b3, b4 are each of the digits.
repeat i from 0 to 9999 b4 := i // 10 ' ones b3 := (i/10) // 10 ' tens b2 := (i/100) // 10 ' hundreds b1 := (i/1000) // 10 ' thousands waitcnt(clkfreq/10+cnt) ' count at ~10Hz
I may refactor the program to use BCD; storing digits in each of the 4 bytes of a Propeller's 32-bit long int, but the code is more readable using one variable per digit.
As for the driver, a segment array, seg, stores the outa cathode pin bits required to turn on each segment (a through g) at each display digit position (1 through 4).
The main loop calls setdigit(digit, value) which sets the cathode bit in the seg array, for the specified display digit and the specified numeric value. For example, displaying "2" in position 3 requires the cathode for position 3 to be low (on) for segments a, b, d, e, g, and high (off) for segments c and f.
repeat setdigit(1, b1) ' set 1's value setdigit(2, b2) ' set 10's value setdigit(3, b3) ' set 100's value setdigit(4, b4) ' set 1000's value bit := AN_A ' start with anode a repeat s from A to G ' loop thru segments outa := seg[s]|bit ' turn on cathodes, anode bit <<= 1 ' next anode bit waitcnt(clkfreq/delay+cnt)
Then, the main loop iterates over the array, seg[A..G], sets the cathode pins, simply with outa := seg[s] and raises the corresponding segment anode pin for each array element by ORing outa with bit, which is the bit corresponding to the current anode pin. How does the array get set with the right cathode?
The setdigit(digit, value) function converts the display digit into the appropriate cathode bit to activate (set low) or deactivate (set high).
Pololu Robotics and Electronics is having its biggest Black Friday/Cyber Monday sale yet, offering huge discounts on over 600 products, along with 11% to 15% off orders over $100! Save big on robots, programmable controllers (including A-Stars, Arduinos, Raspberry Pis, and mbeds), sensors, motor drivers, power supplies, LEDs, actuators, wheels, breadboards, wires, and more. The first doorbuster deals go live Wednesday, November 26, and the sale runs through Cyber Monday (December 1). For details, visit http://www.pololu.com/blackfriday2014
Science Fiction inspired robots that don't require programming (unless you want too)! In 1977, the world invited the Apple II Personal Computer into the home. 2014, ezrobot has launched Revolution, a robot for everyone! Whether you choose the Revolution clip'n'play robots or developer kit, ezrobot is making robotics, well... easy!
Adafruit Black Friday : 15% off plus free stuff. Welcome to the Black Friday sale – 15% off plus all the free items & shipping as you shop! Use code: BLACKFRIDAY on check out. We thought about doing flash sales or complicated codes but that’s a lot of frustrating hoop jumping for everyone, so we came up with what we think is an amazing deal that is straight forward, no stress and valuable – a 15% off discount anything in stock and lots of great free things automatically depending on how much you order.
We are currently offering a FREE Adafruit Perma-Proto Half-sized Breadboard PCB for orders over $100, a FREE Trinket 5V for orders over $150, FREE UPS ground (Continental USA) for orders $200 or more, a FREE Pro Trinket 5V for orders over $250
On Cyber Monday (12/1), everything in our Actobotics category is 20% off. That means everything from Actobotics Kits to DC Motors is marked down. If you’re looking to start exploring the world of robotics, or stock up for your next build, this is a killer chance to do so. Next on 12/1/2014, we are offering hourly flash sales from 7 a.m. to 7 p.m. Mountain Standard Time, with 30-50% off on some of our most popular products. These items have been hand-selected by our employees and are some of our favorite designs! Details: Sparkfun Cyber Monday 2014
BASIC Stamp Sale started Nov 10. Free USPS Priority shipping and 10% off the entire store. Robot kit sale (ELEV-8 Quadcopter, Arlo Robotic Platform System), Best Sellers Sale, and other mystery deals! Also, a free WS2812B module with every order.
GHI Electronics: Black Friday through Cyber Monday sale on FEZ MCU boards and more!
The sale will start this Friday, November 28th and will end Monday, December 1st (UTC-05:00) Eastern Time (US & Canada). Lots of great boards on sale including discontinued models.
Black Friday / Cyber Monday is here at Trossen Robotics! Interbotix & RobotGeek brand kits and parts are 20% off, everything else in the store is 10% off! Use coupon code "Friday14" to redeem your discount at checkout! Offer good from 12/28/2014 - 12/1/2014 *Offer excludes HR-OS1 and HR-OS5 Humanoid Platforms.
Running all week, we will be dropping prices and offering amazing deals on literally hundreds of the most popular items in the HobbyKing catalog. Models, lipos, tools, chargers, we'll be offering amazing discounts from all product categories, so you're almost guaranteed to pick up an amazing deal. If you don't see something you are interested, check back in an hour because our offers will be added and changed constantly. This isn't a week where you want to be away from an internet connection.
You can see that /dev/sdd1, in my case, is the disk partition that was just mounted. It's partition #1 on disk /dev/sdd. In your case, it may be a different device path.
You're interested in writing the kernel image to the disk, not the partition. So remove the partition number to get the disk device path. (For example: if /dev/sdx1 is the partition, /dev/sdx is the disk). In my case, that's /dev/sdd
Writing the Image
You'll use dd to write the image to your disk.
NOTE: Make absolutely certain you are using the disk corresponding to your microSD card.
If you use the wrong device, you could lose data, or overwrite your OS. That's bad.
However, it's easy to avoid making that mistake. Just be careful and pay attention.
Use df to make absolutely certain you have the correct device. Then double-check your command line before you hit return.
Is your kernel image done downloading? Ok, cd into wherever it's saved.
When you run dd, you'll specify the input file, the image, with if=filename and you'll specify the output device, your microSD card device (not partition), with of=device-path. And you'll specify a 4M block size with bs=4M. (Did you doublecheck the device?)
Format your USB drive as FAT32 if it isn't already.
Extract files out of the 7z file you downloaded, which will create an ubuntu folder. The two files inside that folder are update.sh and pcduino_ubuntu_20131126.img (20131126 is the date; there may be a different date on whatever file you grabbed)or whatever the date is on the filename).
Move those files onto the root folder of your USB drive. It doesn't matter if there are other files on your USB drive.
Unmount the flash drive and remove it from your machine.
Serial Debug Monitor
While you wait for the download, let's connect your Serial USB adapter to the debug port on the pcDuino so we can see what is going on. when you install the operating system.
The debug port is a 3-pin header, next to the Menu button on the USB connector side.
pcDuino debug port
Data going into the pcDuino is closest to the USB connector (FTDI: TXO). The middle is ground. The pin closest to the A10 is for data coming out of the pcDuino (FTDI: RXI). Connect your serial USB adapter so that TX coming from the pcDuino goes into the RX pin of your adapter and TX coming out of your adapter is going into RX on the pcDuino.
You previously removed power from your pcDuino and removed the microSD. We're about to power it up. Open your favorite terminal program (for example, minicom), connect to the USB serial adapter. Set the baud rate to 115,200, 8N1.
Begin the Install
Plug in power to your pcDuino and you should see it outputting a long string of text. Eventually it indicates that it is searching for update.sh (remember that file?).
Insert the USB flash drive.
mount udisk succeed
update.sh found, updating rootfs from udisk, please wait...
writing pcduino_ubuntu_20131126.img to nand flash
it will take about 10 minutes to finish... update finished update finished
After some time, the update will complete. Remove the USB flash drive, and reset the board (or power cycle it).
You should see a long string of text fly by. At the end of it you'll see something like this:
[ 6.350000] Warning: this sunxi disp driver will see significant redesign. [ 6.360000] Applications using /dev/disp directly will break. [ 6.370000] For more information visit: http://linux-sunxi.org/Sunxi_disp_driver [ 6.670000] kjournald starting. Commit interval 5 seconds [ 6.670000] EXT3-fs (nandd): using internal journal [ 6.680000] EXT3-fs (nandd): mounted filesystem with ordered data mode [ 7.070000] init: plymouth main process (68) terminated with status 127 [ 7.120000] init: ureadahead main process (70) terminated with status 5
Welcome to Linaro 12.07 (GNU/Linux 3.4.29+ armv7l)