September 29, 2015

USB Relay with LabVIEW

Filed under: Daily — profmason @ 8:12 pm

The IC-Station USB 4 channel relay uses a serial protocol to communicate with any serial device.  The device appears as a virtual COM port and in controlled using 9600 8N1.

The protocol requires the following commands to be sent after initialization before any relays can be addressed.

  • HEX x50  (Should respond xAB)  This is the same as ASCII P
  • 20 ms pause
  • HEX x51  This is the same a ASCII Q

This initialization is so that noise on startup doesn’t toggle any of the relays.

Once the board is initialized, then the individual relays can be addressed by sending a single character of HEX code.   The last four bytes control the 4 relays on the board.

IE sending B00001111  turns all 4 relays on.  B00001111 = x0F

Sending B00000000 turns all relays off.

Testing the module is as simple as opening up putty or any other serial terminal and sending P then Q. This puts the module in receive mode.  Now send 0-O to set the different states of the module.  This works since the last 4 bits of 0-O correspond to the possible states in the 4 relay module.

The module uses a PL2303HX module which will require the latest version of the prolific USB-Serial driver and may not work on windows 8.  The module contains a small 8 bit ST micro and a ULN2303 transistor pack.  It is a shame that they didn’t write a bit more complicated firmware and pull the rest of the pins of the micro out as this could have been a really nice board without them spending any more money.

Here is some sample python code from the ic-station website, note the pyserial module must be installed and it assumes that your device enumerates as COM3:

import serial
import time


def relay_1():
if __name__ == "__main__":

Here is the labview code: USBRelayTest

September 12, 2015

Multiplexing Pololu line sensors for use with VEX Cortex and RobotC

Filed under: Daily — profmason @ 4:15 pm

Pololu sells a variety of the line sensors that are ideally suited for following a 3/4″ line on a contrasting background.  These in the QTR-8 series and the Zumo series.  The QTR-8A sensor pictured at right has 8 IR sensors which will detect a white or black line at a distanced of between 1 and 2 cm from the surface.  These sensors  can be interfaced directly with the analog inputs on the VEX cortex.  However, since the QTR-8A has 8 sensors, it would require all 8 of the analog inputs on the cortex.  In addition, the Analog polling on the Cortex through robot C is slow.  Instead, we will use an Arduino Nano to read the 8 sensors on the QTR-8A and generate a single analog output that contains the position of the line in the sensor.

Image result for rc low pass filter calculator

Hardware assembly:

0. Build an RC filter.  A low pass RC filter will be used to smooth the pulse width modulated output from the arduino to generate a reasonable approximation of an Analog Output that can be read by the Cortex. To determine what values are appropriate you can calculate the roll off frequency of the filter according to f = 1/ (2pi * RC)  For this application you want a roll off frequency of around 1 MHz.

  • Solder your resistor to the ground pin on the Arduino Nano
  • Solder your cap with with one end connected to D3 and the other connected to the other end of the resistor you just soldered to ground.

1.  Solder the end of a male servo connect to the Arduino Nano as follows:

  • Red to 5V
  • Black to the junction of your resistor and capacitor from the RC step above
  • White to Digital 3

2. Solder 10 wires for a strip connector to A0 through A7 plus gnd and 5V.

3.  Solder the other end of the wires you just attached to the Arduino to the Pololu board connecting the

ground to ground, 5V to VCC and the analog inputs to the corresponding sensor output pins on the QTR-8 according to the picture at right.


Below is a program for the Arduino that reads the 8 analog sensors from the QTR-8A, calculate a weighted average, and then outputs an analog signal which contains the location of the black line.  If no black line is detected, the sensor outputs 0.


uint32_t sensor[8];  //Array for Sensor Values
uint32_t sumValues = 0;  //Sum of the Sensor Values
uint32_t color = 0;  //Will be used as a Color flag for black or white lines. Not Implemented
uint32_t valueOut = 0;  //Output value for Analog Output
void setup()
Serial.begin(9600);  //Initialize the Serial Output
pinMode(3, OUTPUT);  //Define Pin3 as low impedance suitable for analog Output
TCCR2A = 0b10100011;  //Setup Fast PWM on timer 2 to run at 56KHz
TCCR2B = 0b00000001;
OCR2B = 128;          //Set Pin3 to run at 50% duty cycle since 8bit.

void loop()
sensor[0] = analogRead(A0);  //Read in analog Values
sensor[1] = analogRead(A1);
sensor[2] = analogRead(A2);
sensor[3] = analogRead(A3);
sensor[4] = analogRead(A4);
sensor[5] = analogRead(A5);
sensor[6] = analogRead(A6);
sensor[7] = analogRead(A7);

valueOut = 0;  //Initialize the variables to calculate the weighted average
sumValues = 0;
for(int i = 0; i < 8; i++) //Loop through each of the Sensors
valueOut += sensor[i]*128*(i);  //Weight the Sensor Values
sumValues += sensor[i];         //Calculate the Sum of the Sensor Values
if(sumValues <= 400)  //This is the cut to throw away data if no line is detected.
valueOut = 0;
valueOut /= sumValues;  //Calculate the weighted average
//Serial.println(valueOut);  //For debugging
OCR2B = (valueOut/4)%256;    //Generate the Analog Output on Pin 3
delayMicroseconds(100);      //Wait a bit so things can settle

April 23, 2015

STEM Center at Fox Valley College

Filed under: Daily — profmason @ 7:22 pm

Mt. SAC is fast tracking a STEM center to provide services to Science and Engineering students.  I had the opportunity to visit the STEM center at FOX valley and take some pictures of what works in their center.  Please click on images to make them larger.

First there are some small group study centers that are made of light weight round tables separated by rolling partitions.  The ones that had round tables with light weight rolling chairs were in use.  The ones with LARGE HEAVY chairs and anchored square tables were not.    The rolling partitions had integrated whiteboards which showed limited use.

Immediately past the area shown in the first picture was a series of tables designed to seat 4 shown at the left below. .  These open areas showed high use and tutoring was taking place at one of the tables on a rolling white board.  The rolling whiteboards seem to get significantly more use then the fixed whiteboards in this space.

Care was taken to use materials on the floor, ceiling and walls to damp noise in the space.

Much of the furniture is on wheels and the floor is carpeted with a very dense patterned weave to allow easy rolling and not show dirt.

Shown on right below is an area adjacent to this area with a series of computer collaboration stations to allows students to work in

station.groups of 2 or 3 on a computer

These did get some use but in general students seemed to prefer open tables and using their own laptops.   If the space is serving as a open computer lab, this is a requirement.  The people pictured whose faces you can see are all workshop participants who have signed releases for their photos to be displayed.

In the back there is a station where the staff monitors the center and there are reminders on the tables for students to “clock in” when they use the center.

 At the left we see the interior area that is separated by the rolling whiteboards. This area gets very little use to the point that humorous drawings left on the whiteboards persist for weeks to months despite the apparently comfortable heavy furniture.   In the distance you see the more popular open area that seats four students comfortably.

The final area shown at right was sets of paired tables that were separated by low glass partitions.

Based on observation and discussion with the center lead, these tables get moderate use, but typically by one student studying alone.

These tables get more use then the tables separated by high partitions but not as much as the tables that are in the open.


  • Rolling whiteboards are useful for student working in groups and for tutoring.
  • Open tables are better the tables separated by partitions.
  • Low partitions are better then tall partitions.
  • Moveable furniture is better then fixed furniture.  Light furniture is better then heavy.
  • Power was provided on the walls and no where else.

Finally here is a picture of the FAB lab that is near the STEM center.    In discussion, this space has some of the highest traffic per square foot of any space on campus. It is fronted with a glass wall and glass door and is on the aisle were the engineering technology faculty offices and classroom area.  It is NOT directly supervised, but faculty are always within sight of the space and it is closed when faculty are not in the area.

The FAB lab has:

  • Laser Cutter
  • 3D printer
  • Hand tools both mechanical and electrical
  • Injection molder.

In addition we had a chance to visit one of their model classrooms.  This is a great way to offer the types of interaction that we would like to see in a reduced space.  The current physics instructor loves teaching in this room.  Of particular note is the oval tables that compactly seats 6 students and has a white board surface which means that we don’t need the large space for whiteboards.


January 26, 2015

Rover 5 USB control

Filed under: Daily — profmason @ 1:53 am

The dagu Rover 5 is a terrific small robotics platform.  The form factor is small and lightweight, yet it can navigate over carpet thresholds and most household environments.  The platform is further distinguished by being inexpensive and including reasonably accurate wheel encoders.

This platform will serve as a mobile based for an Odroid computer.  To simplify matters, all the drive will be wrapped up on a Arduino Nano microcontroller.  The motors and encoders are interfaced to the Arduino and the Arduino recieves serial commands to drive the chassis.

Here is the list of commands that are implemented:

  1. &1 gets the current encoder data
  2. &2 resets the encoders
  3. &3 sends a encoder based drive command.  (direction, distance (cm), power (0-255))

Direction is as follows:

  • 1 Straight
  • 2 Pivot Turn
  • 3 Swing Turn
  • 4 Stop

4.   &4 Raw Motor Commands  (Left Motor Power, Right Motor Power.)

//2 Motor Rover 5 Drive Library
// Arduino Uno with L298N

#define enR 5 //Enable Right Motor used to set speed
#define enL 6 //Enable Left Motor
#define inR1 8 //Input 1 Right Motor 2 inputs to control driver
#define inR2 9 //Input 2 Right Motor
#define inL1 10 //Input 1 Left Motor
#define inL2 11 //Input 2 Left Motor
#define encoderRightA 3//Encoder Right Interrupt pin
#define encoderRightB 4//Encoder Right
#define encoderLeftA 2//Encoder Left Interrupt pin
#define encoderLeftB 7//Encoder Left

#include <Encoder.h> //improved encoder library

Encoder rightEnc(encoderRightA, encoderRightB); //Create encoder objects
Encoder leftEnc(encoderLeftA, encoderLeftB);

int distance = 0; //global distance used by the drive
boolean moving = 0; //flag to tell if the platform is moving
int Lpower = 0; //global powers for speed control
int Rpower = 0;
boolean speedControl = 1; //Flag to turn speed control on and off.
char command = 0; //command read from serial port.
void setup() {
 Serial.println("Basic Rover 5:");

// initialize the digital pins as an output.
 pinMode(enR, OUTPUT); //Motor R Enable
 pinMode(enL, OUTPUT); //Motor L Enable
 pinMode(inR1, OUTPUT); //Motor R
 pinMode(inR2, OUTPUT); //Motor R
 pinMode(inL1, OUTPUT); //Motor L
 pinMode(inL2, OUTPUT); //Motor L

analogWrite(enR,80); //Set default speeds for motors

// the loop routine runs over and over again forever:
void loop() {
 delay(5); //This sets the speed of the loop. To fast and miss serial data.

//Write a routinue that takes as input a pair of motor powers and then drives the motors at those speeds.
// +255 to -255 is full forward to full backward

void driveMotors(int powerR, int powerL)
 Rpower = abs(powerR);
 Lpower= abs(powerL);
 if (powerR >= 0) //Drive the Right motor forward if >= 0
 digitalWrite(inR1, LOW);
 digitalWrite(inR2, HIGH);
 else //Drive the Right motor backward if power < 0
 digitalWrite(inR1, HIGH);
 digitalWrite(inR2, LOW);
 if (powerL >= 0) //Drive the left motor forward if >= 0
 digitalWrite(inL1, LOW);
 digitalWrite(inL2, HIGH);
 else //Drive the left motor backward if power < 0
 digitalWrite(inL1, HIGH);
 digitalWrite(inL2, LOW);


//Write a routinue to service the encoders so that we don't have to block on drive.
void checkEncoders()
 if ((abs( > distance) || (abs( > distance)) // if we have gone the distance
 moving = false;
 // Speed Control
 if (speedControl)
 int proportionalError = abs( abs(;
 analogWrite(enR,Rpower - proportionalError/3);
 analogWrite(enL,Lpower + proportionalError/3);

//Write a routinue to go a given distance from the encoders. Take as input
// Motor Power negative values go backwards
// Distance in ticks

void straightEncoders(int power, unsigned int travel)
 distance = travel;
 moving = true;
 speedControl = true;
//write a routinue to do a differntial turn
// take as input the speed and the number of ticks.
//positive power turns right negative left.
void pivotTurnEncoders(int power, unsigned int angle)
 distance = angle;
 moving = true;
 speedControl = true;

//write a routinue to do a swing turn
// take as input the speed and the number of ticks.
//positive power turns right negative left.
void swingTurnEncoders(int power, unsigned int angle)
 if (power > 0){
 distance = angle;
 moving = true;
 speedControl = false;

void stopMotors()
 digitalWrite(inR1, LOW);
 digitalWrite(inR2, LOW);
 digitalWrite(inL1, LOW);
 digitalWrite(inL2, LOW);

void readSerialData()
//We want to read from the serial port.
// &1 gets the current encoder data
// &2 resets the encoders
// &3 sends a drive command.
// (direction, distance (cm), power (0-255))
// Direction is as follows:
// 1 Straight
// 2 Pivot Turn
// 3 Swing Turn
// 4 Stop
// &4 Raw Motor Commands
// Leftmotor Power, Right Motor Power.
 if( Serial.peek( ) == '&' )
 { ); //this just gets rid of the & char
 command = ); //command is the next char in buffer
 if ( command == '1' )
 else if ( command == '2' )
 else if ( command == '3' )
 int inDirection = Serial.parseInt();
 int inDistance = Serial.parseInt();
 int inPower = Serial.parseInt();
 switch (inDirection) {
 case 1:
 case 2:
 case 3:
 else if ( command == '4' )
 Lpower = Serial.parseInt();
 Rpower = Serial.parseInt();

 Serial.println( -10 );
 else if( Serial.peek( ) != -1 ) //get rid of anything that's not part a command
 { );

September 12, 2014


Filed under: Daily — profmason @ 5:08 am

The OpenOLLO is designed to interface the power of the OpenCM 9.04 microcontroller with the wide variety of parts available for Robotis Dream, OLLO and STEM products.  It consists of a 3D printed case suitable for the OpenCM9.04 which matches the form factor of previous OLLO products such as the CM100 and new products such as the CM150.  This allows the Dream, OLLO and STEM product line to be used with a controller that was designed from the ground up to use the OpenIDE, the processing based integrated development environment that is intended to identical to the Arduino programming environment.  Using the OpenIDE allows access to a wide variety of existing sensors and curricular materials to be used with the the flexibility to the OLLO, Dream and Stem products.

The OpenOLLO case includes press fit mounting pegs for the OpenCM so that it can easily be inserted and removed.  There are side openings that allow access  to all 24 digital IO pins and 10 analog IO pins.  In addition, a top mounted port allow a battery packs using the standard 2 pin Robotics battery connector (either Ollo standard AA packs or the rechargable LiPo batteries). Additional ports allow access to the micro-usb programming connector, a four pin serial port for debugging,  and a pair of robotis AX series servo ports as is shown in the figure at right. A single OLLO rivet is used as an extension to allow access to the reset button integrated into the OpenCM board.

The design allows standard OLLO parts to be attached using the OLLO plastic pop rivet system.  An inexpensive 3D printer such as the mendelmax 1.5 can hold sufficient tolerance to generate holes that are compatible with the OLLO system.

The image below shows the OpenCM 9.04 mounted inside the case.

The image below allows for a size comparison between the CM100 product and the OpenOLLO.  The OpenOLLO is the same width as the CM100, but is exactly twice as long, due to the longer natures of the OpenCM 9.04 PCB.

Older Posts »

Powered by WordPress