Twitter Hardware (Arduino)
Autor: Bruno Soares | Publicado: 2009-04-24T15:13:00-03:00

Twitter Hardware é um projeto que utiliza a placa Arduino e um Display LCD para exibir as mensagens do Twitter. Para que a Arduino tenha as mensagens escrevi um software em Adobe AIR / Flex, que se conecta ao Serial Proxy enviando o conteúdo para a Arduino. Arduino:/** * Twitter Hardware *  * @author   Bruno Soares * @link     http://www.bsoares.com.br * @language Arduino / C++ */// Includes#include // Defines#define DEBUG_PIN                 13#define COMMAND_RIGHT             0#define COMMAND_LEFT              1#define QUANTITY_COMMANDS         2#define ANALOG_PIN_COMMAND_RIGHT  0#define ANALOG_PIN_COMMAND_LEFT   1#define ANALOG_PIN_SPEED          2#define MESSAGE_START             94  //  94 = ^#define MESSAGE_END               126 // 126 = ~#define SERIAL_BOUND              9600#define LCD_LINES                 2#define LCD_COLUMNS               16#define ANIMATE_CMD_WIDTH         4// Global variablesunsigned long time;// LiquidCrystal display with:// rs on pin 12// rw on pin 11// enable on pin 2// dbs 3, 4, 5, 6, 7, 8, 9, 10LiquidCrystal lcd(12, 11, 2, 3, 4, 5, 6, 7, 8, 9, 10);// Analog configurationunsigned int analogCmd[QUANTITY_COMMANDS];unsigned int analogSpeed = 0;// Control commandsboolean changingSpeed = true;boolean readingSerial = false;boolean pressedCmd[QUANTITY_COMMANDS];unsigned int lastSpeed = 0;// Massageschar currentMessage[400] = "No messages.";unsigned int currentMessageLenght;// ------------------------------------------------------------------------ \\// Programvoid setup() {  Serial.begin(SERIAL_BOUND);  pinMode(DEBUG_PIN, OUTPUT);    smartDelay(10);  lastSpeed = analogSpeed;    presentation();  changingSpeed = false;}void loop() {    // Show current message  clearLcd();  writeLongTextInLcd(currentMessage);  smartDelay(applySpeed(7000));  }void presentation() {  lcd.clear();  writeLongTextInLcd("Twitter Hardwareby Bruno Soares");  smartDelay(3000);}void refreshAnalogVars() {  analogCmd[COMMAND_RIGHT] = analogRead(ANALOG_PIN_COMMAND_RIGHT);  analogCmd[COMMAND_LEFT]  = analogRead(ANALOG_PIN_COMMAND_LEFT);  analogSpeed              = analogRead(ANALOG_PIN_SPEED);}// ------------------------------------------------------------------------ \\// [INI] Commandsvoid detectCommand() {  unsigned int i = 0;  while (i < QUANTITY_COMMANDS) {    if (analogCmd[i] > 500 && !pressedCmd[i]) {      executeCommand(i);    }    i++;  }}void executeCommand(int command) {  pressedCmd[command] = true;  digitalWrite(DEBUG_PIN, 1);    if (command == 0) {    animateNext();  } else {    animatePrevious();  }    currentMessage[0] = 'L';  currentMessage[1] = 'o';  currentMessage[2] = 'a';  currentMessage[3] = 'd';  currentMessage[4] = 'i';  currentMessage[5] = 'n';  currentMessage[6] = 'g';  currentMessage[7] = '\0';  currentMessageLenght = 7;    Serial.print(command);    while (analogCmd[command] > 500) {    smartDelay(4);  }    pressedCmd[command] = false;  digitalWrite(DEBUG_PIN, 0);}void animateNext()  {  for (unsigned int i = 0; i < LCD_COLUMNS + ANIMATE_CMD_WIDTH; i++) {    if (i < LCD_COLUMNS) {      lcd.setCursor(i, 0);      lcd.print(">");      lcd.setCursor(i, 1);      lcd.print(">");    }    delay(5);    if (i - ANIMATE_CMD_WIDTH >= 0) {      lcd.setCursor(i - ANIMATE_CMD_WIDTH, 0);      lcd.print(" ");      lcd.setCursor(i - ANIMATE_CMD_WIDTH, 1);      lcd.print(" ");    }    delay(30);  }}void animatePrevious() {  for (int i = LCD_COLUMNS; i >= -ANIMATE_CMD_WIDTH; i--) {    if (i >= 0 && i < LCD_COLUMNS) {      lcd.setCursor(i, 0);      lcd.print("<");      lcd.setCursor(i, 1);      lcd.print("<");    }    delay(5);    if (i + ANIMATE_CMD_WIDTH < LCD_COLUMNS && i + ANIMATE_CMD_WIDTH >= 0) {      lcd.setCursor(i + ANIMATE_CMD_WIDTH, 0);      lcd.print(" ");      lcd.setCursor(i + ANIMATE_CMD_WIDTH, 1);      lcd.print(" ");    }    delay(30);  }}// [END] Commands// ------------------------------------------------------------------------ \\// [INI] Messagesvoid detectSerialMessage() {  if (Serial.available() > 0 && !readingSerial) {    if (Serial.read() == MESSAGE_START) {      serialReadMessage();    }  }}void serialReadMessage() {  digitalWrite(DEBUG_PIN, 1);  readingSerial = true;  currentMessageLenght = 0;    iniReading:  if (Serial.available() > 0) {    unsigned int _char = Serial.read();    if (_char == MESSAGE_END) {      goto endReading;    } else {      currentMessage[currentMessageLenght++] = _char;      delay(2);      goto iniReading;    }  }  goto iniReading;    endReading:  currentMessage[currentMessageLenght] = '\0';  digitalWrite(DEBUG_PIN, 0);  readingSerial = false;}// [END] Messages// ------------------------------------------------------------------------ \\// [INI] LCD manipulationvoid writeLongTextInLcd(char text[]) {  writeInit:  clearLcd();  unsigned int cml = currentMessageLenght;  int loops = -1;  unsigned int chars = 1;  while (text[loops++ + 1] != 0) {    if (chars == 17) {      lcd.setCursor(0, 1);      smartDelay(applySpeed(600));      if (cml != currentMessageLenght) goto writeInit;    } else if (chars == 33) {      smartDelay(applySpeed(3000));      clearLcd();      if (cml != currentMessageLenght) goto writeInit;      chars = 1;    }    lcd.print(text[loops]);    smartDelay(applySpeed(60));    if (cml != currentMessageLenght) goto writeInit;    chars++;  }  Serial.print(2);}void writeInLcd(char text[], int quantity) {  for (unsigned int i = 0; i < quantity; i++) {    if (text[i] == 0) {      do {        lcd.print(" ");      } while (i++ < quantity);      break;    } else {      lcd.print(text[i]);    }  }  delay(2);  //smartDelay(5);}void clearLcd() {  lcd.setCursor(0, 0);  smartDelay(5);  lcd.print("                ");  smartDelay(applySpeed(400));  lcd.setCursor(0, 1);  smartDelay(5);  lcd.print("                ");  lcd.setCursor(0, 0);  smartDelay(applySpeed(0));}// [END] LCD manipulation// ------------------------------------------------------------------------ \\// [INI] Speedvoid detectChangeSpeed() {  if (changingSpeed) return;  if (!(lastSpeed < analogSpeed + 6 && lastSpeed > analogSpeed - 6)) {    showGraderSpeed();  }}void showGraderSpeed() {  changingSpeed = true;  digitalWrite(DEBUG_PIN, 1);  lcd.clear();  writeInLcd("Speed:", LCD_COLUMNS);    // Create display velocity  showSpeed:  for (unsigned int i = 0; i < 10; i++) {    int charsSpeed = map(analogSpeed, 0, 1023, 0, LCD_COLUMNS);    int percentSpeed = map(analogSpeed, 0, 1023, 0, 100);    char* percentString;    itoa(100 - percentSpeed, percentString, 10);    percentString = strcat(percentString, "%");    lcd.setCursor(7, 0);    writeInLcd(percentString, 4);    charsSpeed = LCD_COLUMNS - charsSpeed;    lcd.setCursor(0, 1);    for (unsigned int x = 1; x < LCD_COLUMNS + 1; x++) {      if (x <= charsSpeed) {        lcd.print(">");      } else {        lcd.print(" ");      }    }    lastSpeed = analogSpeed;    smartDelay(40);  }    // Verify  for (unsigned int i = 0; i < 10; i++) {    if (!(lastSpeed < analogSpeed + 6 && lastSpeed > analogSpeed - 6)) {      goto showSpeed;    }    smartDelay(40);  }    // Finalize  lcd.clear();  changingSpeed = false;  digitalWrite(DEBUG_PIN, 0);}long applySpeed (unsigned int value) {  return map(analogSpeed, 0, 1023, 0, value);}// [END] Speed// ------------------------------------------------------------------------ \\// [INI] Milliseconds controllervoid smartDelay(int milliseconds) {  if (milliseconds < 2) {    noDelayFunctions();    delay(milliseconds);    return;  }  do {    delay(1);    milliseconds -= noDelayFunctions();    milliseconds -= 1;  } while (milliseconds > 0);}int noDelayFunctions() {  time = millis();    // [INI] No delay functions here  refreshAnalogVars();  detectChangeSpeed();  detectCommand();  detectSerialMessage();  // [END] No delay functions here    return millis() - time;}// [END] Milliseconds controllerActionScript (usando Serialproxy):package br.com.bsoares.air.airtwitterhardware{ import flash.events.Event; import flash.events.EventDispatcher; import flash.events.IOErrorEvent; import flash.events.ProgressEvent; import flash.net.Socket;  /**  * Message Control  * Control messages between the Arduino and in AIR  * Application using Serial Proxy.  *   * @author Bruno Soares  * @link   http://www.bsoares.com.br  */ public class MessageControl extends EventDispatcher {  // Properties  private var _host:String;  private var _port:uint;  private var _socket:Socket;  private var _messages:Array;   private var _currentMessage:uint;  private static var _instance:MessageControl;  private static var _allowInstantiation:Boolean = false;    // Constructor  public function MessageControl()  {   if (!_allowInstantiation)    throw new Error("Use instance property (this is a Singleton Class).");   init();  }    // Logic  private function init():void  {   _host = "127.0.0.1";   // COM2   _port = 5332;   _messages = [ ];   _currentMessage = 0;   socketConnect();  }    private function socketConnect():void  {   _socket = new Socket();   _socket.addEventListener(ProgressEvent.SOCKET_DATA, onSocketData);   _socket.addEventListener(Event.CLOSE, onSocketClose);   _socket.addEventListener(IOErrorEvent.IO_ERROR, onSocketIoError);   _socket.connect(_host, _port);  }    private function processData(data:String):void  {   trace("Arduino command:", data);   switch (true)   {    // Send next message    case data == "2" || data == "0":    {     sendNextMessage();     break;    }    // Send previous message    case data == "1":    {     sendPreviousMessage();     break;    }   }  }    private function sendMessage(message:String):void  {   if (message == null || message == "")    return;      trace("Message:", message);      // MESSAGE_START   _socket.writeUTFBytes("^");   _socket.flush();      // MESSAGE   for (var i:uint = 0; i < message.length; i++)   {    _socket.writeUTFBytes(message.charAt(i));   }   _socket.flush();      // MESSAGE_END   _socket.writeUTFBytes("~");   _socket.flush();      dispatchEvent(new Event(Event.CHANGE));  }    private function sendNextMessage():void  {   _currentMessage = _currentMessage == _messages.length - 1 ? 0 : _currentMessage + 1;   sendMessage(_messages[_currentMessage]);  }    private function sendPreviousMessage():void  {   _currentMessage = _currentMessage == 0 ? _messages.length - 1 : _currentMessage - 1;   sendMessage(_messages[_currentMessage]);  }    // Events  private function onSocketData(event:ProgressEvent):void  {   while (_socket.bytesAvailable > 0)    processData(_socket.readUTFBytes(1));  }    private function onSocketClose(event:Event):void  {   socketConnect();  }    private function onSocketIoError(event:IOErrorEvent):void  {   trace(event.text);  }    // Getters and Setters  public static function get instance():MessageControl  {   if (_instance == null) {    _allowInstantiation = true;    _instance = new MessageControl();    _allowInstantiation = false;   }   return _instance;  }    public function set messages(value:Array):void  {   _currentMessage = 0;   _messages = value;   if (_messages.length > 0)    sendMessage(_messages[0]);  }    public function get messages():Array  {   return _messages;  }    public function get currentMessage():uint  {   return _currentMessage;  } }}Esquemático:Baixe o código fonte aqui.Conteúdo relacionado:Post original: http://blog.bsoares.com.br/arduino/twitter-hardwareMais fotos: http://www.flickr.com/photos/bsoares/sets/72157616923436133/Arduino: http://arduino.cc/Adobe AIR: http://www.adobe.com/products/air/Adobe Flex: http://www.adobe.com/products/flex/LiquidCrystal Library: http://arduino.cc/en/Reference/LiquidCrystal?from=Tutorial.LCDLibraryTwitter: http://twitter.com/