Wednesday, 12 March 2014

Teensy Motor

If I'm going to build my robot army I need them to move, so lets start with DC motors!

I have a couple laying around (most people I know do for some reason).

Using the easiest interface I know I'll stick with the Teensy.

First lets just get the motor going:



Here's a basic circuit that powers the motor with 5 volts but triggers the motor with a transistor.







It's a very easy circuit, I stole it ada fruits tutorial to do the same thing with a full arduino.

Their example code allows you to specify the motor speed between 0 and 255 but I only have 2 hands so I'm going to turn it on and off.
 int motorPin = 20;  
 void setup()   
 {   
  pinMode(motorPin, OUTPUT);  
 }   
 void loop()   
 {   
    analogWrite(motorPin, 255); //Motor turn on  
    delay(1000);  
    analogWrite(motorPin, 0); //Motor turn off  
    delay(1000);  
 }   


Saturday, 8 March 2014

BBC Weather Reporter LCD

Following on with my LCD screen and button combo I've built a simple BBC Weather Reporter.

We start by getting the weather from BBC Weather RSS for our area, to make manipulating the information easier I threw together a class for dealing with the results. Then I grab the parts I'm interested in and sent them to the USB.

On the Teensy I need to wait for the results, it's immature at the moment so I just use a timer for up to 10 seconds.

Then we print the data out, the only issue I can find is that the Teensy doesn't recognise degrees at the moment so I'm getting some funky characters.

Here's the Python:
 #!/usr/bin/python2.7  
 import urllib2  
 from DayWeather import DayWeather  
 from lxml import etree  
 #Import my bits  
 from DayWeather import DayWeather  
 #IMPORT USB stuff  
 from time import sleep  
 import numpy as np  
 import sys  
 import serial, time  
 from serial.tools import list_ports  
 def getWeather():  
      url="http://open.live.bbc.co.uk/weather/feeds/en/2643743/3dayforecast.rss"  
      rawMetGroup = urllib2.urlopen(url).read()  
      root = etree.XML(rawMetGroup)  
      build_text_list = etree.XPath("//item")  
      items=build_text_list(root)  
      days = []  
      for item in items:  
        day = item.find("title").text.split(":")[0]  
        desc = item.find("description").text  
        dw = DayWeather(day,desc)  
        days.append(dw)  
      return days  
 if __name__ == "__main__":  
   ports = [port[0] for port in list_ports.comports()]  
   print "Using serial port %s" % (ports[-1])  
   serial = serial.Serial(ports[-1],baudrate=9600, timeout=0, writeTimeout=1)  
   serial.flushInput()  
   serial.flushOutput()  
   while True:  
      content = serial.readline() # Read the newest output from the Arduino  
      output=""  
      if content == "GetWeather":  
           weather = getWeather() #The Weather has been requested       
           for w in weather:  
             if len(output) > 0:  
                output = output +"#"  
             output=output+w.toString().encode('utf-8')  
           print output  
           serial.write(output)  
      sleep(.1) # Delay for one tenth of a second  

Here's the Python Weather class:
 # -- coding: utf-8 --  
 import string  
 class DayWeather:  
   def __init__(self,day,details):  
      self.day = day  
      self.details = details.split(",")  
   description = "A basic object to read an parse an BBC weather object from their RSS feed"  
   author = "Michael Davies"  
   def getPart(self,part):  
      for detail in self.details:  
        if detail.strip().startswith(part):  
           return detail.split(":")[1].strip()  
     return ""  
   def getDay(self):  
      return self.day  
   def getMaxTemp(self):  
      temp = self.getPart("Maximum")  
      return "Max:" + temp  
   def getMinTemp(self):  
      temp = self.getPart("Minimum Temperature")  
      return "Min:" + temp  
   def toString(self):  
      return self.day + "," + self.getMaxTemp() + "," + self.getMinTemp()  

Here's the C for the Teensy:
 #include <Wire.h>   
 #include <LiquidCrystal_I2C.h>  
 // Set the LCD address to 0x27 for a 16 chars and 2 line display  
 LiquidCrystal_I2C lcd(0x27, 16, 2);  
 String weather[3][3];  
 void setup(){  
  pinMode(7, INPUT_PULLUP); //Set pin 7 to INPUT_PULLUP, this uses the inbuilt resistor on the pin  
  lcd.begin();  
  Serial.begin(9600); // USB is always 12 Mbit/sec  
  lcd.noBacklight();  
 }  
 void loop(){  
  checkButton(); //Simple Check  
  delay(250);  
 }  
 void checkButton(){  
   if (digitalRead(7) == LOW ) {  
    Serial.print("GetWeather");  
    lcd.backlight(); //Turn the light on       
    lcd.clear();  
    lcd.home(); //Start at row 1  
    lcd.print("LOADING"); //Show something is happening  
    getWeather();  
    displayMessage();  
    lcd.clear(); //Clear the result at the end  
    lcd.noBacklight();  
   }   
 }  
 void getWeather(){  
  //Check for up to 10 seconds  
  for (int t = 0; t<40; t++){  
   if (Serial.available()){  
    readUSBToWeather();  
    return;  
   }  
   delay(250);  
  }  
  return;   
 }  
 void readUSBToWeather(){  
   String content = ""; //Set up return variable  
   char character; //char to read from USB  
   int dayLine = 0; //Day Number  
   int infoLine = 0; //Line Number  
   while(Serial.available()) { //While there is more to read, do more  
    character = Serial.read(); //Read the char  
    if (character =='#') {    
     weather[dayLine][infoLine] = content;  
     content="";  
     dayLine++;  
     infoLine=0;  
    }else if( character == ','){  
     weather[dayLine][infoLine] = content;  
     content="";  
     infoLine++;  
    }else{  
     content.concat(character); //Add it to the return variable  
    }  
    delay (10); //make sure we don't act too quickly and assume it's over before it really is  
  }  
  if (content != ""){  
    weather[dayLine][infoLine] = content; //Put the last bits on the end  
  }  
  return;  
 }  
 void displayMessage(){  
  //If the first day has data assume the rest is full  
  if (weather[0][0] == ""){  
   lcd.clear();  
   lcd.home();  
   lcd.print("No Message");  
   delay (2000);  
   lcd.noBacklight();  
   return;  
  }  
  //For each day  
  for (int day = 0;day < 3; day++){   
   //For each other row in the data  
   for (int info = 1; info < 3; info++){  
    lcd.clear();//Empty the screen  
    lcd.setCursor(0, 0);//Make sure we are home  
    lcd.home(); //Start at row 1  
    lcd.print(weather[day][0]); //Put the day  
    lcd.setCursor(0, 1);//Set row 2  
    lcd.print(weather[day][info]); //Put the weather  
    delay (2000); //Show this for 2 seconds  
   }  
  }  
  weather[0][0] = ""; //empty our first day to ensure we don't print when we shouldn't  
  return;  
 }  

Here's a quick picture of it working:



Wednesday, 26 February 2014

Listening to your Teensy

Now I can write to my Teensy it would be nice if I can listen to what it has to say, possibly more useful.

So we start with the Python this time:
 #!/usr/bin/python2.7  
 from time import sleep  
 import serial  
 from serial.tools import list_ports  
 if __name__ == "__main__":  
   ports = [port[0] for port in list_ports.comports()]  
   print "Using serial port %s" % (ports[-1])  
   serial = serial.Serial(ports[-1],baudrate=9600, timeout=0, writeTimeout=1)  
   serial.flushInput()  
   serial.flushOutput()  
   while True:  
      content = serial.readline() # Read the newest output from the Arduino  
      if content:  
           print content       
      sleep(.1) # Delay for one tenth of a second  

Now when I run this program it will wait for a message and if there is anything write it out.

Now we can add to the sketch:
 #include <Wire.h>   
 #include <LiquidCrystal_I2C.h>  
 // Set the LCD address to 0x27 for a 16 chars and 2 line display  
 LiquidCrystal_I2C lcd(0x27, 16, 2);  
 String oldContent; //Keep this between usb reads();  
 void setup(){  
  pinMode(7, INPUT_PULLUP); //Set pin 7 to INPUT_PULLUP, this uses the inbuilt resistor on the pin  
  lcd.begin();  
  Serial.begin(9600); // USB is always 12 Mbit/sec  
  oldContent=""; //Initialise this variable  
 }  
 void loop(){  
  String content = getString(); //Get the USB content  
  checkButton(); //Check for a result  
  //If there was USB content display it  
  if (content != ""){  
   content.concat(" "); //Add another character  
   oldContent = content;//Save the content  
  }  
  //If there is something to display  
  if (oldContent!=""){  
   displayMessage(oldContent); //show me!  
  }else{  
   //Otherwise check again soon!  
   delay(250);  
  }  
 }  
 String getString(){  
  String content = ""; //Set up return variable  
  char character; //char to read from USB  
  while(Serial.available()) { //While there is more to read, do more  
    character = Serial.read(); //Read the char  
    content.concat(character); //Add it to the return variable  
    delay (10); //make sure we don't act too quickly and assume it's over before it really is  
  }  
  Serial.print(content); //Echo back the content heard on USB  
  return content;   
 }  
 void displayMessage(String message){  
  if (message!=""){ //Make sure there is something to show  
    lcd.home(); //Start at row 1  
    printRows(message,0); //print the message, possibly on 2 rows  
    delay(2500); //Show the first screen for a while, give people a change to read  
    for (int posCounter = 0; posCounter < message.length(); posCounter++){ //For all of the chars  
     checkButton();  
     printRows(message,posCounter); //print the message, possibly on 2 rows  
     delay(600);  
    }  
    delay(600);  
  }   
 }  
 void printRows(String message, int pos){  
    lcd.clear();//Clear the screen again  
    lcd.setCursor(0,0);  
    lcd.print(message.substring(pos,pos+16));  
    if (message.length() >16){  
     lcd.setCursor(0, 1); //Set to the second row  
     lcd.print(message.substring(pos+16,pos+32));  
    }  
 }  
 // a little check for a button  
 void checkButton(){  
   if (digitalRead(7) == LOW ) {  
    Serial.print("button pressed");  
   }   
 }  

There are two new bits here. First we echo back what we heard on USB after it was received. Second we have a couple of checks for a button on pin 7. I turned this into a function so I can add the check in more places as there are quite a few loops that could miss the event.

This function would allow me to break out of my loops if the button was pressed if I returned true instead of just printing.

Not a major development but now with the two python programs I can dynamically update my message and listen to my device for anything happening locally.

Next goal is to have a "service" react to the button and trigger something happen like get a REST service response to display a message on the LCD, baby steps :)

Here's a picture of a cat:

Tuesday, 25 February 2014

From Python to Teensy!

Now I have Teensy reading from serial it's probably worth trying to put something there to receive.

I took the code in blog post on the forum's for Teensy and hacked it a bit to only send a simple string via the USB.

Here's my Code:
 #!/usr/bin/python2.7  
 import numpy as np  
 import sys  
 import serial, time  
 from serial.tools import list_ports  
 if __name__ == "__main__":  
   ports = [port[0] for port in list_ports.comports()]  
   print "Using serial port %s" % (ports[-1])  
   serial = serial.Serial(ports[-1],baudrate=9600, timeout=0, writeTimeout=1)  
   serial.flushInput()  
   serial.flushOutput()  
   data = sys.argv[1]  
   print data  
   try:  
     start = time.time()  
     iter = 0  
     serial.write(data)  
   except KeyboardInterrupt:  
     serial.close()  

 Here's an animated picture of the message going past:

Of course I need to tidy the python up, handle params properly and check some state but for a few minutes work it's not bad.

Teensy Scrolling text!

Today I have been playing around with the screen, this time reading from the serial port and printing the message. The code to read from USB is really simple and can be found in the examples so I won't go into that.

What I want to do is do scrolling text over two lines! The inbuilt function scrollDisplayLeft() doesn't really do the job and it scrolls the whole panel so I rolled my own function.

Very quickly the code is below:

 #include <Wire.h>   
 #include <LiquidCrystal_I2C.h>  
 // Set the LCD address to 0x27 for a 16 chars and 2 line display  
 LiquidCrystal_I2C lcd(0x27, 16, 2);  
 String oldContent; //Keep this between usb reads();  
 void setup(){  
  lcd.begin();  
  Serial.begin(9600); // USB is always 12 Mbit/sec  
  oldContent=""; //Initialise this variable  
 }  
 void loop(){  
  String content = getString(); //Get the USB content  
  //If there was USB content display it  
  if (content != ""){  
   content.concat(" "); //Add another character  
   oldContent = content;//Save the content  
  }  
  //If there is something to display  
  if (oldContent!=""){  
   displayMessage(oldContent); //show me!  
  }else{  
   //Otherwise check again soon!  
   delay(250);  
  }  
 }  
 String getString(){  
  String content = ""; //Set up return variable  
  char character; //char to read from USB  
  while(Serial.available()) { //While there is more to read, do more  
    character = Serial.read(); //Read the char  
    content.concat(character); //Add it to the return variable  
    delay (10); //make sure we don't act too quickly and assume it's over before it really is  
  }  
  return content;   
 }  
 void displayMessage(String message){  
  if (message!=""){ //Make sure there is something to show  
    lcd.home(); //Start at row 1  
    printRows(message,0); //print the message, possibly on 2 rows  
    delay(2500); //Show the first screen for a while, give people a change to read  
    for (int posCounter = 0; posCounter < message.length(); posCounter++){ //For all of the chars  
     printRows(message,posCounter); //print the message, possibly on 2 rows  
     delay(600);// Wait a bit as the LCD refresh is bad  
    }  
    delay(600); // Little extra wait, possibly not needed  
  }   
 }  
 void printRows(String message, int pos){  
    lcd.clear();//Clear the screen again  
    lcd.setCursor(0,0); //Got to line 1  
    lcd.print(message.substring(pos,pos+16)); //Get row 1 and print it  
    if (message.length() >16){ //Check for a row 2  
     lcd.setCursor(0, 1); //Set to the second row  
     lcd.print(message.substring(pos+16,pos+32)); //Print row 2  
    }  
 }  

Not rocket science but it might help someone.

Sunday, 23 February 2014

Teensy 3.0 I2C LCD screen. NOW WITH BUTTON!

So after playing with the screen I'd now like to make it only display something for a short time. I'd also like it to be dynamic updating instead of just showing the message while it's on.

So I hooked up a switch to pin 7 like so:

Then I wrote the sketch below.
 #include <Wire.h>   
 #include <LiquidCrystal_I2C.h>  
 // Set the LCD address to 0x27 for a 16 chars and 2 line display  
 LiquidCrystal_I2C lcd(0x27, 16, 2);  
 int count; //Used to keep display alive while we are reading information  
 void setup()  
 {  
     pinMode(7, INPUT_PULLUP); //Set pin 7 to INPUT_PULLUP, this uses the inbuilt resistor on the pin  
      // initialize the LCD  
      lcd.begin();  
     lcd.clear();  
     lcd.noBacklight();  
     count = 0; //Initialise the variable  
 }  
 void loop()  
 {   
   //Check to see if we have pushed a button   
   if (digitalRead(7) == HIGH ) {  
    // If the count if > 100 reset the counter and clear the screen  
    if (count >100){  
    lcd.clear();  
    lcd.noBacklight(); //Turn off the light  
    count =0;  
   }  
   else{  
    //If the count is not yet at 100 then display the current count  
    lcd.clear();  
    lcd.home();  
    lcd.print("Counting");  
    lcd.setCursor(0, 1); //Set to the second row  
    lcd.print(count);  
   }  
  } else {  
   //The button has been pressed  
   lcd.home();//Send to home  
   lcd.backlight(); //Turn the light on       
   lcd.print("Hello World"); //Print a basic message    
   count = 1; //Let the count begin  
  }  
  //If we have started counting then keep counting  
  if (count >0){   
   count++;  
  }   
  // Wait a short time, then we check again  
  delay(200);  
 }  

BOOM!

Does the job for now, next I need to read something from USB and have that the thing being displayed.

Teensy 3.0 I2C LCD Screen

I'm getting back into Electronics after a long time away.

A long time ago I backed the Teensy 3 project and now I've got the time I'm looking into how to use.

So here it is:

A really basic I2C LCD display being driven by the Teensy.





As a noob it took me some time to work it out so I thought I would share what little I worked out.

So with the Teensy it really quite simple, wire the GND to the GND and VIN to VCC, then wire pin 18 to SDA and 19 to SCL. Finally Wire the 2 pull up resistors (4.7k) from 18 and 19 to the VCC.

It should look like a better version of this:

Now to program the Teensy, I would read their guide as I can't do it justice.

In order to write to the screen you need to know what address to send the commands too.

Again I found a great resource that looks for any I2C devices connected and tells you the address it's available on. Check out Ardunio Playgroud for the sketch.

My address was 0x27 so that's what I'm going to use.

Now to write our own sketch:
 #include <Wire.h> //Read in the librries  
 #include <LiquidCrystal_I2C.h>  
 // Set the LCD address to 0x27 for a 16 chars and 2 line display  
 LiquidCrystal_I2C lcd(0x27, 16, 2);  
 void setup()  
 {  
  //Basic Variable Setup  
  lcd.begin();  
  lcd.home();   
  lcd.print("Hello World");  
 }  
 void loop()  
 {  
 }  

That's it! Next I'm going to start adding a button and then moving onto reading information from USB to display.