DaddyOh's Blog

Making, Cooking, Living

First Robotics

| Comments

If you have or will have kids in K12 school or you can influnce other parents then you need to know about FIRST Robotics. FIRST is a program with 4 levels of participation, 3 of which involve building and competing with robotics. Ever since discovering FIRST in 2006, the program has become one of the most important thing in my life. Sure I work, and love my work, and have a beautiful wife I love dearly and two girls in late high school and college. FIRST Robotics has made a difference in my kids life in unmeasureable ways. And even more importantly, it touches hundrend of thousand of kids around the world.

FIRST builds interest in Science Technology Engineering and Math (STEM). But it also build character and imporant life skills in its participants. Leadership, confidence, dispute management, problem solving, team work and critical thinking are just a few of the competencies it builds in those that participate.

I could write pages and pages on FIRST. But I won’t. If you want to know more, go to their web site FIRST Robotics, search for videos on youtube and ask others what they know about FIRST.

1086 Blue Cheese Robotics Team

My youngest is on a FIRST Robotics Competition team FRC at Deep Run High School. 1086 Blue Cheese has been around for about twelve years and has about 60 students on the team. They build a 120lb robot in a little more than six weeks and compete at one or two tournaments each year. 1086 promotes STEM around the world. They are involved at the federal and state level lobbying for STEM education and they help others get engaged in STEM and FIRST Robotics activities. They efforts make learning fun for many others. Many of their alumni go on to major in Engineering in college.

FIRST is Fun, FIRST is Cool, FIRST is our Life

Below are some pictures and videos of FIRST team activities I have been involved with over the years. These are FIRST Lego League FLL and FIRST Robotics Competion FRC pictures.

1086 is Featured in this 2014 RVA MakerFest video

What is a Maker? What is the Maker Movement? Find out in this Science Matters’ video filmed at the RVA MakerFest, September 27, 2014.

 

Mentoring a 2014 FIRST Lego League Team

1086 Team Members and Friends After Lobbying at the Va State Level

Various Shot of 1086 at the 2014 RVA MakerFest

Team 956 Building the Mission Pieces at the Start of the Season

Now Go and Make Something!

Reading Quadrature Encoders With mBuino Mbed

| Comments

PID Control Learning System Part 3

Introduction

As part of my efforts to learn about motor control and PID conrollers I needed to figure out how to read Quadrature Encoders so that I can measure and adjust motor speed. Using encoders I should be able to measure motor speed with greater precision and accuracy than would be possible from counting each output shaft rotation. And with the right encoders I should be able to measure the motor speed on a regular basis (say every 0.1 second) which makes the PID control simplier and more predictiable.

Rotary encoders are devices that count rotations either of the output shaft or if a geared motor, the primary motor shaft. You will find optical encodes that trigger when a light beam is interupted and magnetic encoders that trigger when a magnet passes close to a hall effect sensor.

Quadrature encoders are when there are two sensors on the same ring. Quadrature encoders provide several benefits:

  • Greater trigger resolution over single sensors, hence faster
  • Higher counts per rotation and this leads to greater precision and accuracy
  • The ability to know what the rotational direction is at any point in time

With the addition of a third sensor you can also measure the position of the wheel (or whichever part is rotating). Three sensors is a bit advanced and is not part of this blog post.

There are a lot of resources on the web talking about using encoders. For my purpose I just need some sample code that runs in an mbed device. The code below is designed for a mBuino platform. However it also runs on an NXP LPC1768 (with a few minor changes) and should be adaptable to all mbed platforms if they have enough pins available.

Geared Motors and Encoders

When the encoder is attached to the primary motor shaft of a reduction geared motor you can get very high output shaft resoultion from the encoders. Consider the motor I used from pololu which is stated to use a 30:1 reduction gear, with a maximum output shaft speed of 350 RPM. When using both sensors for the qaudrature encoder the motor triggers 64 times for each primary shart rotation.

Lets do the math for one output shaft rotation:

1 output rotation * 30 primary motor rotations / ourpur rotations  = 30 primary rotations / output shaft rotations
30 primary rotations * 64 triggers / rotation = 1920 triggers / output shaft rotation

The documentation on the motor I used states:

The quadrature encoder provides a resolution of 64 counts per revolution of the motor shaft when counting both edges of both channels.

This is important because most encoder libraries have a configuration setting for which encoding scheme to use.

This demonstration program used the mbed QEI library provides for X2 and X4 encoding. We need X4 since we are measuring both the rise and fall of the output traces for both sensors. The code sample shows how this all works.

I’m pretty new to using mbed and encoders so I validated the calculated motor speed (output shaft rotations per minute) using a hall effect sensor with a disc with a magnet on the output shaft. The good new is the values are identical. I guess that means I’m doing something right! You can see the setup in the pictures and video at the end of the post.

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include "mbed.h"
#include "QEI.h"
#include "USBSerial.h"
/*
  Using an mBuino mbed device (can use any mbed) and the mbed QEI Library
  
  Measure motor output shaft speed every ~0.1 second using
  a pololu quadrature encoder and motor
  
  License: Apache License, Version 2.0
  http://www.apache.org/licenses/LICENSE-2.0.html
  December 30, 2014
  Copyright: Eric F Palmer, 2014
  Email: eric [at] ericfpalmer [dot] [com]
   
  This code could be simplified but I have left it alone
  because it works and you have access to the delta values for
  further analysius and debugging
  
  See notes at the bottom of the file
  
*/

USBSerial pc;
QEI wheel (P0_13, P0_11, NC, 64, QEI::X4_ENCODING);
Timer t;
int startTimeUs, endTimeUs;
int deltaUs = 0;
int startPulse, endPulse;
int deltaPulse = 0;

float calcRpm(float deltaTimeSec, int deltaPulse){
    // motor ratio = 30 (different for different motors)
    // motor CPR = 64 (also may vary for different motors, encoder types) 
    return 60.0 * ((deltaPulse / deltaTimeSec) / (30.0 * 64.0));
}

int main() {
    startTimeUs = t.read_us();
    startPulse = wheel.getPulses();
    t.start();
    while(1){
        wait(0.1);
        endTimeUs = t.read_us();
        endPulse = wheel.getPulses();
        deltaUs = endTimeUs - startTimeUs;
        deltaPulse = endPulse - startPulse;
        pc.printf("%.1f\r\n",calcRpm(deltaUs/1000000.0, deltaPulse));
        wheel.reset();
        startPulse = wheel.getPulses();
        startTimeUs = t.read_us();
    }
}

/*
 Pololu 64 CPR qaudrature encode
 The motor I tested is http://www.pololu.com/product/1443
 RED motor power A up to 24V 
 BLK motor power B 
 GRN encode ground  
 BLU encoder Vcc 3.5 to 20V (using 5 V)
 YEL encoder output A (P0_13)
 WHT encoder output B (P0_11)
 
 
 */

Motor and bracket


Breadboard


Video Showing Motor Running

Test setup for measuring motor speed using quadrature encoders. See the related blog post and other video http://youtu.be/RdpVkhmFDRA http://daddyoh.us/blog/2015/01/02/reading-quadrature-encoders-with-mbuino-mebed/

Serial Output Showing RPM

Shows the calculated motor speed (RPM) for a test with an mBuino mbed device and a 30:1 pololu motor. See the related video http://youtu.be/ilo41DnuZrU and blog post. http://daddyoh.us/blog/2015/01/02/reading-quadrature-encoders-with-mbuino-mebed/

Now Go Make Something!

Motor PID Control System - the Hardware

| Comments

PID Control Learning System Part 2

In this post I will detail the hardware used for the motor PID control expereiments. You should refer to these posts for background information.

Hardware

Here is a list of the hardware parts that make up the test framework and circuit:

You can do these experiments with just about any DC brushed motor, a suitable power supply and PWM based motor controller. In later blog post I will include the code for these tests. But for now I’m justing listing and showing the hardware.

I’m lucky to have a great power supply, but a wall wart or battery will work fine as long it supports the current drain of your motor.

Motor and bracket


Motor, Test Framework and Photointerrput Device


Motor Disc


Closeup of the disc used with the photointerrupter


mBuinoPhotointerrupter


Scavanged photointerrupter attached to hook and loop material with epoxy


Motor Conroller


The PWM based Motor Controller (2 channels, using on one channel for now)


Breadboard


Breadboarded Circuit


Breadboard and motor controller


The Breadboard with the Motor Controller Attached


You can create your own test framework for these experiments. Measuring RPM can be done several ways in addition to using a photointerrupt circuit. Hall Effect transistors are commonly used as well. You should be able to use many Arduino models, mbed platforms or other microcontrollers. What is important is measuring the speed of the motor (RPM) accurately and having a PWM based motor controller to change the motor speed.

YwRobot Breadboard Friendly Power Supply

| Comments

Recently I ordered some breadboards on ebay. The order included 2 YwRobot 545043 Breadkboard Friendly power supplies.

Powersupply


YwRobot 545043 Powersupply Inserted into 2 ¼ inch wide breadboard

I just love this little Power supply (~$2.49). It can be powered by a 6.5-12V supply and has both 3.3V and 5V outputs. This blog post by Peter Vis has a very detailed review that describes it nicely.

The power supply fits into a 2 ¼ wide breadboard (2 rails). You can power each rail with 5V or 3.3V separately or turn off either rail. With the proliferation of 5V and 3.3V microcontroller boards (Arduinos and mbed devices like the mBuino) having an inexpensive and versatile 5V and 3.3V power supply handy is important.

Just set the jumpers for each rail supply voltage you want and insert it into one end of the breadboard.

I hope you find this useful, if you do please leave a comment.

Now Go Make Something!

Live Charting From Mbed Devices

| Comments

PID Control Learning System Part 1

I’ve not had much experience with PID controllers, so I thought it might be useful to build a test platform with these components:

  • A microcontoller platform (mbed, Arduino)
  • DC brushed motor
  • A way to measure motor rotational speed in RPM (Photo-Interrupt transistor or Hall Effect transistor)
  • Microcontroller software to measure, control and report speed
  • Ability to collect data in realtime and live chart the data

To provide visual feedback and the ability to iterate quickly through a bunch of manual settings in the software, I wanted the ability to collect data from the microcontroller platform in realtime and chart that data as it happens.

This post serves as a proof-of-concept and focuses on getting fake data from the microcontroller to my Mac OS X system via the USB Serial port and charting the data in Python in realtime.

Microcontroller Platform

I’ve been working with mbed devices and Arduinos lately and decided it would be fun to start with the mBuino mbed controller. It is inexpensive ($10) and has the pinouts needed to meet the requirements outlined above. The code should be easy to port to other platforms like the Arduinos or other mbed devices like my favorite, the NXP LPC1768.

The mBuino data generation program is simple and only generates fake data. It does not measure motor rotation. That way you can focus on just the fundamentals of data transmission, receiving data and charting.

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/*
   generate sample data and send to the serial port

   loop runs a set number of times and then stops
   so data acquisition system end-point
   can write the data to a file if desired

   License: Apache License, Version 2.0
   http://www.apache.org/licenses/LICENSE-2.0.html
   December 20, 2014
   Copyright: Eric F Palmer, 2014
   Email: eric [at] ericfpalmer [dot] [com]
 */

#include "mbed.h"
#include "USBSerial.h"

USBSerial pc;  // defaults to 9,600 baud

float pi=3.14159265359;
float sValue; // sin value
float cValue; // cosine
int counter = 0;
// don't write so fast to the serial port that it can't keep up
// 30 ms is about 33.3 RPS [Hz] or 2000 RPM
// 13 ms is about 4,500 RPM
int delayMs = 13;

// put some randomness in the cosine value
float randValue(float cValue)
{
    int rValue = 500 - rand() % 1001;
    return cValue + rValue / 1000.0;
}

int main()
{
    wait_ms(3000); // wait so that you can start up a listener on the mac os x system
    pc.printf("#Start\r\n");
    // 72 points for each 0 to 360 degree output loop
    float degree = 0.0;
    while (counter<10*72) {
        sValue = sin(degree*pi/180);
        cValue = cos(degree*pi/180);
        // CSV like output, 5 values, 2 can serve as X axis and 3 can server as Y axis
        // gives you lots of choices
        pc.printf("%i,%f,%f,%f,%f\r\n", counter, degree, sValue, cValue, randValue(cValue));
        degree = degree + 5;
        wait_ms(delayMs);
        counter = counter + 1;
    }
    // write marker out so the other end-point can flush and close any files it might have open
    pc.printf("#Stop\r\n");
}

Testing the mbed Program You want to start a terminal window right after the mBuino is started. You can use the mac app terminal and issue this command:

screen /dev/tty.usbmodem1421 9600

This connects to the same serial port used by the mBuino. Note that your serial port may be different. I use Iterm2 instead of terminal and have a profile set up so I can start up this terminal window, run the screen command all with a simple hot key.

After a couple of seconds you should see output start to scroll past like:

#Start
0,0.000000,0.000000,1.000000,1.334000
1,5.000000,0.087156,0.996195,0.801195
2,10.000000,0.173648,0.984808,1.407808
3,15.000000,0.258819,0.965926,0.857926
4,20.000000,0.342020,0.939693,1.180693
...
716,3580.000000,-0.342016,0.939694,1.270694
717,3585.000000,-0.258816,0.965927,1.015927
718,3590.000000,-0.173643,0.984809,0.588809
719,3595.000000,-0.087152,0.996195,0.622195
#Stop

Charting Software

Charting is done using matplotlib version 1.4.2 under Python version 2.7.5 on Mac OS X.

The liveCharting Phtho program:

liveChart.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# Inspired from  http://www.lebsanft.org/?p=48
# License: Apache License, Version 2.0
# http://www.apache.org/licenses/LICENSE-2.0.html
# December 20, 2014
# Copyright: Eric F Palmer, 2014
# Derived from http://www.lebsanft.org/?p=48
# Email: eric [at] ericfpalmer [dot] [com]
# xaxis on plot is just arbitrary number of the point ploted
# data is saved to a file for more robust analysis in other tools (e.g., excel, R Studio, etc.)

import serial
import numpy as np
from matplotlib import pyplot as plt
import sys
import time


def usage():
    print ""
    print "Arguments supplied ", str(sys.argv[1:])
    print "Usage: python liveChart.py [mbuino|lpc1768|arduino] dataFileName"
    print "       Note: arduino not yet implemented"
    print "       program will save all data lines to dataFileName"
    print "Example:"
    print "       python LiveChart.py mbuino data.csv"


if not len(sys.argv) == 3:
    print "2 arguments expected", len(sys.argv), "found."
    usage()
    exit(1)

#open serial port
if str(sys.argv[1]) == "mbuino":
    ser = serial.Serial('/dev/tty.usbmodem1421', 9600, timeout=1, bytesize=8, parity='N', stopbits=1)
elif str(sys.argv[1]) == "lpc1768":
    ser = serial.Serial('/dev/tty.usbmodem1422', 57600, timeout=1, bytesize=8, parity='N', stopbits=1)
elif str(sys.argv[1]) == "arduino":
    print "Arduino devices not yet implemented"
    usage()
    exit(1)
else:
    print "Microcontroller Device", str(sys.argv[1]), "not supported"
    usage()

#open output datafile
f = open(str(sys.argv[2]), 'w')
f.write('Data capture\n')

# set plot to be interactive
plt.ion()

print "Setting up matplotlib for chart"
plt.figure(figsize=(10, 5))
plt.ylabel('Fake Data')
plt.title("Plot sin() and some random number\nnear the cos() value")
# 72 pts for 360 degrees so lets display 2 cycles
y1data = [0] * 72 * 2
y2data = [0] * 72 * 2
ax1 = plt.axes()
line1, = plt.plot(y1data)
line2, = plt.plot(y2data)
# limit the range of values for Y
plt.ylim([-1.5, 1.5])

#start data collection
plotData = True
while plotData:
    data = ser.readline().rstrip()
    #todo remove the next line
    # print data # just to check
    values = data.split(",")
    if len(values) == 5: # the number of data values expected in CSV string
        y1data.append(values[2]) # sin value
        y2data.append(values[4]) # some random values
        del y1data[0]
        del y2data[0]
        # TODO what does this do
        line1.set_xdata(np.arange(len(y1data)))
        line1.set_ydata(y1data)  # update the data
        line2.set_xdata(np.arange(len(y2data)))
        line2.set_ydata(y2data)  # update the data
        plt.draw()
    elif (data == "#Stop"):
        f.flush()
        f.close
        plotData = False
    else:
        # bad data received so just ignore that line
        pass
    f.write(data + "\n")
print "#Stop Encountered, ending live chart\nEnter ctrl-C to end program"

response = raw_input('Do you want to save the chart as chart.png? [Y/N]: ').strip()
if response.capitalize() == 'Y':
    print "Saving the chart to \"plot.png\" in the current working directory"
    plt.savefig("plot.png", format='png')

Run this code from the command line:

python liveChart.py mbuino data.csv

Once the mBuino sends this line:

#Stop

liveChart.py will flush the data to the file you supplied on the command line and will prompt you for saving the final chart to a file. If you respond with “Y” then the plot will be saved in the current working directory.

Example saved plot file


Sample plot.png

What About MS Windows?

I focus 99% of my hobby time on MAC OS X and a variety of microcontrollers. It should be possible, and maybe easy, to port this to MS Windows Systems. This article on Reading Arduino Serial using Python refers to the use of Windows. If you get this working on windows please post a comment and let us know about your experiences.

What is Next?

This live charting proof-of-concept gives us a mbed model for writing data to a live charting system and provides sample code in Python for live charting. Now this is working I have the ability to measure motor RPM and control it using a PID controller. My hope is I will be able to learn a lot about PID controllers. So it is time to finish my motor control mbed code and see what I can learn.

I hope you find this useful, if you do please leave a comment.

Now Go Make Something!

NeoPixel Test on Mbed

| Comments

I will be using several of these 8 LED NeoPixel Sticks from Adafruit in a Persistence of Vision (POV) project soon. The target POV MicroController I will probably use is based on the ARM mbed platform.

So thought I would test NeoPixel Stick on a NXP LPC1768 and if that goes well then a mBuino platform which is the desired target device for my POV.

I will add a blog pos url here soon.

The project uses this NeoPixel library by Jacob Bramley. This library uses the SPI bus for controlling the timing and the author states that this library should support interrupt driven code (with some limitations). The POV prototypes I will create will be interrupt driven once per rotation so I figured this would be a good library to test.

The NeoPixel Stick have 4 connections 2 GNDs, POWER (+5V) and one for the control signal. The control signal is plugged into P5 on the LPC1768, and we are taking power off of the VU pin (5.0v USB out). I have also tested this powering the stick from an external power supply. Both works nearly flawlessly.

Initially I had a problem with the stick showing colors and lighting LEDs that I did not program in to the code. The stick had long 9 inch leads between the mbed and the stick. If I touched these leads the stick would act erratically. I assume this was due to the high speed communications that the stick depends ons for its control signals. Once I shortened the leads the stick performed great.

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/* 
License: Apache License, Version 2.0
http://www.apache.org/licenses/LICENSE-2.0.html
Copyright: Eric F Palmer, 2014
Email: eric [at] ericfpalmer [dot] [com]
 */

#include "mbed.h"
#include "neopixel.h"

// This must be an SPI MOSI pin.
#define DATA_PIN p5

// this program has the number of LEDs fixed at 8 for the Adafruit NeoPixel Stick

void setPixel(neopixel::Pixel * buffer, uint32_t index, uint8_t red, uint8_t green, uint8_t blue, uint32_t length)
{
    if (index >= length ) {
        return;
    }
    buffer[index].red = red;
    buffer[index].green = green;
    buffer[index].blue = blue;
}

void brightnessTest(neopixel::PixelArray array, neopixel::Pixel * buffer)
{
    // step through three colors with the same brigtness
    uint32_t i;
    for (i = 0x00; i<= 0xC8; i = i + 0x0A) {
        setPixel(buffer, 0, i, 0x00, 0x00, 8);
        setPixel(buffer, 2, 0x00, i, 0x00, 8);
        setPixel(buffer, 4, 0x00, 0x00, i, 8);
        // clear the rest
        setPixel(buffer, 1, 0x00, 0x00, 0x00, 8);
        setPixel(buffer, 3, 0x00, 0x00, 0x00, 8);
        setPixel(buffer, 5, 0x00, 0x00, 0x00, 8);
        setPixel(buffer, 6, 0x00, 0x00, 0x00, 8);
        setPixel(buffer, 7, 0x00, 0x00, 0x00, 8);
        array.update(buffer, 8);
        wait_ms(250);
    }
}

// not tested yet, use at own risk
void clearAll(neopixel::PixelArray array, neopixel::Pixel * buffer, uint32_t length)
{
    uint32_t i;
    for (i = 0; i< length; i = i +1) {
        setPixel(buffer, i, 0x00, 0x00, 0x00, length);
    }
}

int main()
{

    // Create a temporary DigitalIn so we can configure the pull-down resistor.
    // (The mbed API doesn't provide any other way to do this.)
    // An alternative is to connect an external pull-down resistor.
    DigitalIn(DATA_PIN, PullDown);

    // The pixel array control class.
    neopixel::PixelArray array(DATA_PIN);

    // 8 is the number of pixels
    uint32_t numLeds = 8;
    neopixel::Pixel buffer[numLeds];
    int waitMs = 1000;

    /*
     * control the colors and brightness by turing on (or off) red, gree, blue
     * values should be hex 0x00 (off) to 0xFF full on for each color
     *
     * these LEDs are very bright and don't need to be driven much to get
     * sufficient light out of then 
     *
     * achieve other colors by mixing RGB
     *
     * this code is not pretty but it works
     */

    while (1) {

        // Turn on blue for the 4th LED
        // All LEDs off
        for (int i = 0; i < numLeds; ++i) {
            setPixel(buffer, i,0x00, 0x00, 0x0, numLeds);
        }
        setPixel(buffer, 3, 0x00, 0x00, 0x12, numLeds);
        array.update(buffer, numLeds);
        wait_ms(waitMs);

        // All LEDs white
        // All LEDs off
        for (int i = 0; i < numLeds; ++i) {
            setPixel(buffer, i,0x00, 0x00, 0x0, numLeds);
        }
        for (int i = 0; i < numLeds; ++i) {
            setPixel(buffer, i,0x12, 0x12, 0x12, numLeds);
        }
        array.update(buffer, numLeds);
        wait_ms(waitMs);

        // All LEDs yellow
        // All LEDs off
        for (int i = 0; i < numLeds; ++i) {
            setPixel(buffer, i,0x00, 0x00, 0x0, numLeds);
        }
        for (int i = 0; i < numLeds; ++i) {
            setPixel(buffer, i,0x23, 0x23, 0x00, numLeds);
        }
        array.update(buffer, numLeds);
        wait_ms(waitMs);

        // All LEDs off
        for (int i = 0; i < numLeds; ++i) {
            setPixel(buffer, i,0x00, 0x00, 0x0, numLeds);
        }
        array.update(buffer, numLeds);
        wait_ms(waitMs);
    }
}

Please leave comments if you find this useful.

POV blog posts

Persistence of Vision (POV) Part 1

| Comments

I’ve been thinking about Persistence of Vision (POV) projects lately. I want to make a rotating cylinder POV device eventually that has a multi-color display.

In preparation for that project I have been watching some videos and reading up on POV. I’m presenting some of these references for your enjoyment as well.

Lets start off with Mr. Wizzard ,Don Herbert, introduction to POV.

Mr. Wizard demonstrates how persistence of vision works. Subscribe now for more science, nature and technology clips from the 1980’s Nickelodeon show, Mr. Wizard’s World, every week on #WizardWednesdays.

The Wikipedia article is also pretty informative.

The Wikipedia article talks about POV displays constructed of 2D lights that repeat in the same place every couple of milliseconds. So lets start with a 2 millisecond refresh for an LED on a rotating device.

(1000 ms / s) / 2 ms = 500 Hz or 500 rotations per second. Sounds okay right?

Lets turn that into revolutions per minute.

500 Hz (or 500 revolutions / second) * 60 seconds / min = 30,000 RPM. What 30,000 RPM? Something must be wrong here. So lets keep looking for more info. The same article talks about modern film with a refresh rate (frame rate) of 24 Frames / Second and up. I’m not sure that comparing film, where the images is changing constantly and an led display, where we want character display persistence is fair. But lets try anyway.

24 FPS = 24 Hz = 24 Cycles / Second * 60 Seconds / Minute = 2,400 RPM. Now that sounds reasonable. But lets keep checking. Lets look at some videos and related articles if we can find any.

I like this one for the simplicity and that the parts are easy to obtain.

Build It: http://www.pyroelectro.com/projects/pyro_propeller_clock_pov/

While this design is simple and seems easy to build the density of LEDs could be improved using LEDs based on the WS2812 device. At 5.0 mm per LED these chips can be tightly packed resulting in `2 LEDS / cm or 5 / inch. If you go looking for LEDs based on the WS2812 chip you will find that Adafruit calls their versions of these NeoPixels.

The above video references an article that lists the fan part as 3,800 RPM. So lets check this now:

3,800 RPM / 60 Seconds / Minute = 63 Hz.

At 63 Hz the refresh time is 1000 ms / 63 cps = 15.7 ms for the image passing by our eyes in the same place.

Okay so 2,400 RPM to 3,800 RPM might be more reasonable. I don’t think we need 30,000 RPM and have plenty of motors lying around that can spin at 3,000 to 4,000 RPM.

This video shows a nifty clock display and they say that they are using a hard disk drive motor (HDD) to spin the lights. Also the board has a nice LED density.

See another clock: http://www.youtube.com/watch?v=6dygwdisUj0 The prototype of the propeller clock made of the rotating 33 LEDs line and the HDD motor. See more: http://www.elektroda.pl/rtvforum/topic944484.html

So how fast does a HDD spin? So 7,200 RPM and of course higher.

Now lets go looking for spinning vertical cylinder POVs.

When you watch this video you will see what is possible. To the best I can tell this is a commercial product. Regardless, this shows what a high quality vertical display would look like. If you pause the video at 7 seconds you can get a good look at the whole device from the side. It looks like there are three columns of LEDs in one vertical section. Advancing to 11 seconds you will see there are three vertical sections with three columns of LEDs. The extreme information (pixel) density of this display is a result of 9 total columns of LEDs.

Persistencia de la visión - Alta Calidad de Imagen POV High Quality POV - RGB LED www.dartec.mx

This one looks monochromatic and 5 seconds in you can see how it is constructed. Very simple design from a spinning column standpoint. I wish I knew what the rotational speed is of this device.


The final version of the above POV device can be seen here. At 22 seconds you can see the base controls. Rotor, Motor and Hauptsch which is german for “Current Main”. So the builder is using main (house) current to drive the motor of this one. At 2:10 you can see 2 flat ones and a vertical one.

Three models: - horizontal, yellow leds - horizontal, red leds - vertical, yellow leds Connection to PC via Bluetooth.

One more flat one. This one is packaged nicely.

Auto-dimming, highly configurable, remote control Propeller Clock based on 41 LEDs, a PIC16F886 microprocessor, and a 80x80x38mm 12VDC fan. The circular housing (starting life as a cake tin - I kid you not) has two functions: It affords physical protection against the spinning circuit board; it reduces the generated wind noise very significantly. The clock has options to either have a transparent rear clock face for that ‘floating in the air’ display effect, or to have a dark rear clock face for a high contrast display. Firmware and circuit is courtesy of user Hp41C at forum http://www.hobbielektronika.hu/forum/topic_180.html Many thanks must go to: Hp41C (at the hobbielektronika.hu forum) for the firmware/circuit Rob for helping design some pretty images Amjid for taking various deliveries when I was away Stuart for the use of his sandpaper+blocks Terry for the use of his jigsaw Martin for the use of his clamps

And now a globe. I love the way he can “draw” on the globe.

This is one of our lates projects. For schematics, layouts, and code see our project page: http://www.solderlab.de/index.php/led-projects/rgb-globe Best regards, Pepe PS: There is a small typo at the very beginning of the clip: It should be “2 PCBs” instread of “3”.

The maker describes the project details in the Globe project information.

In the forum data is a statement about the rotational speed of the globe. “It’s round about 10-20 Turns per second (depending on the motor voltage).

That would br 600 RPM to 1,200 RPM.

So now I can start to work on a design for a flat display (horizontal) so I can work out the electronics and the programming. Then, if time and money permit, maybe I’ll do a vertical display.

Now go out and make something.

Measuring DC Motor Speed Using a Optointerrupter

| Comments

Recently I deconstructed an old HP Office All In One printer. In the process I scavanged 3 devices that look like this:

HP Branded Opto Device

Scavenged Opto Device

I’ve seen these before when deconstructing printers and assumed they were some sort of optointerrupter devices. After some research online and I found a device at Digi-Key that looks similar. The photo of the OPTO SENSOR 5MM DARK-ON TRANS looks similar and the scavanged device acts like the name in the sense that the sensor turns on the logic output when the light can’t get to the sensor (e.g., dark).

These devices work by having a infrared LED on one end of the slot and a phototransistor at the other end. There are transistor like devices in the catalogs and there are logic devices as well. Since the current flows when the light is blocked I assumed this was a logic based device and not just a raw optotransistor for the sensor. I am not sure if this is correct, but it doesn’t matter since I was able to get it to work.

I played with the device a little and decided I could build something that could measure the reveloutions per minutes (RPM) of some of my hobby DC motors.

The schematic of how I wired this up is shown below. Since I don’t know the actual device in use, the schematic of the actual optointeruppter should be asumed to be wrong, but close enough.

Schematic

Schematic

I assembled a small jig using Actobotics™ parts from ServoCity and attached a 12-24V hobby motor to the jig. I cut a 70mm disk out of some stiff paper and attached it to the small gear on the motor shaft. The opto device was glued to a piece of hook and loop material that the other half was also glued to the jig.

Front of Jig – Notice Slot In Disk

Front of Jig

The Top of the Jig

Jig Top

I’ve been playing with a ARM based mbed processor lately and figured this would be a great project to try with my NXP LPC1768 (Cortex-M3) mbed microcontroller and mbed application board.

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/* 
 With a disk that is solid color and a open (transparent slot) in the disk:
 the opto transistor acts like a closed switch when the disk is solid 
 (no light passes).  Therefore we want to count each time the transistor acts
 like it is open.

 License: Apache License, Version 2.0
 http://www.apache.org/licenses/LICENSE-2.0.html
 Copyright: Eric F Palmer, 2014
 Email: eric [at] ericfpalmer [dot] [com]

 */

#include "mbed.h"
#include "C12832_lcd.h"
C12832_LCD lcd; //Graphics LCD

DigitalOut myled1(LED1);
InterruptIn opto(p18);
int startTime;
int endTime;
float delta;
volatile int (ct);
Timer t;

void ISR1()
{
    ++ct;
}

int main()
{
    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("Start");
    wait(1.0);
    ct = 0;
    t.start();
    startTime = t.read_ms();
    opto.fall(&ISR1);
    while(1) {
        endTime = t.read_ms();
        # collect counts for 5 seconds
        if (endTime - startTime > 5000) {
            delta = (endTime - startTime)*1.0;
            lcd.locate(0,0);
            lcd.printf("ct:%i d:%i    \r\n",ct, (int)(delta));
            lcd.printf("RPM %i       ", (int)((ct * 1000.0 / delta)*60.0));
            startTime = t.read_ms();
            ct = 0;
        }
    }
}

You can see the results on the OLED display shown below. With the hobby motor I was able to get the motor to slow down to ~203 RPM at 2.5 volts before it stalled and up to ~3500 RPM at 27.8 Volts.

I’m very happy with how this worked out. I was hopeful to get some sort of measurement but did not know how responsive the actual opto device was going to be. In a word this was “fantastic”.

OLED Display on the mbed Application Board

Display

Scope Trace at ~203 RPM

Scope

I was really hopefuly that the rise and fall times for the opto device were fast enough that I could measure 3500 RPM. You can see from the trace below that at 3500 RPM the device has a fall time of about 45us and a rise time of 320us. So lets assume the total dip time (fall + transparent slot time + rise) is about ~500us at this speed. If this holds up (and the slot time will go down) then this device should be able to measure a motor speed of more than 1000Hz or 1000 Cycles / Sec * 60 Sec/Min or 60,000 RPM. I don’t think I have any motors faster than maybe 5000 RPM. It would cool to test something in the 10,000 RPM to 20,000 RPM range.

Scope Trace at ~3467 RPM

Scope

All in all I’m pretty excited by these results. I hope to code up an Ardunio version and test that soon. I will post the results here for those of you that want to do this with an Arduino.

Now Go Make Something!

Self Balancing Robot Part 1 - Platform

| Comments

This is the first of several posts about my experiencing building a self balancing robot.

Robot Platform

My immediate goal is to build a self balancing robot using off-the-shelf components as a learning exercise. Once I get the robot working I will make a lot of improvements including switching the embedded microprocessor platform from Arduino to mbed. Eventaully I will design my own components as an exercise in skill improvement.

Note that the platform described here is not yet a working robot. Once I get the robot balancing I will write another post about that code and will update this post as well.

If you have questions about any of this please post comments and I will do the best I can to answer them.

Controller Components

Motors, wheels and brackets

Smart car Robot Self-balancing Kit Wheel+ 12V Motor+Motor bracket+Connector – Motors are ASLONG DC Motor JGA25-370-12V-122RPM

Miscellaneous

  • No. 8 threaded rod, 12 inches long (Qty 4)
  • No. 8 hex nuts
  • DPDT switch (using only one throw) so you can use a DPST switch if you can find one
  • Various bolts, nuts and stand-offs to attach components to the platforms
  • Baltic Birch Plywood 3mm-1/8” x 12” x 12”
  • USB cable for programming the UNO
  • Several LEDs and resistors for indicator lights
  • Wires, shrink wrap plastic and more

Power

Two of the AA battery cases are wired in series to provide 12 volts for the motor shield to power the motors. One AA battery case is used to power the Arduino UNO and 9DOF board.

I wired the battery cases up to the DPDT switch and added the barrel jack plug (Male) to the output of the single case for plugging into the Arduino.

Platform Levels

Top

Top of Robot

  • on off switch
  • 2 Battery cases for motor power
  • Indicator LEDs

Middle

Bottom of Robot

  • 9 DOF board for Gyro and Accelormeter sensing
  • Battery case to power the Arduino UNO

Bottom

Underneath the Robot

  • Motor Shield stacked on Arduino UNO
  • Motors, wheels, brackets

Platform Dimensions are about 3 inches x 5.5 inches x ⅛ inch

Improvements

Oh I have so many things I will do different next time. But until I get the robot running it is premature to decide on improving the platform.

Keep It Simple Wire Dispenser

| Comments

Dispenser

In my projects I use a variety of wire colors and guages. I usually have several projects going at one time, so and I needed a portable way to bring the wires to the projects. I took a cheap plastic box from a big box store and cut some holes in the ends. I cut some ¼ inch threaded rod to size, added the wire reels to the rod and bolted the whole thing together.

For one last improvement I used an old solidering iron to melt a hole in the front for each of the 26 guage reels. I threaded the wires through the holes and now I have a simple and effective wire dispenser.

Dispenser

The 26 AWG reels of wire are from Pololu.

Somethings the simplest way is the best way. Now go build someting.