2013-04-26 51 views
1

當使用此腳本來閃爍引腳12上的LED時,腳本不會超過line27,其中引腳12設置爲高電平。沒有錯誤消息。Python-Firmata和Arduino,影響冷凍的腳本結構

import json 
    import urllib 
    from firmata import * 
    from pprint import pprint 
    import time 
    import serial 

    countTweet = 0 
    a = Arduino('COM13') #Insert this before the while loop = it never actually works 
    a.delay(2)   

    while True: 
     try: 
      response = urllib.urlopen('http://search.twitter.com/search.json?q=%23happy&result_type=recent&rpp=1&filter:retweets').read() 
     except IOError: 
      pprint('no internet connection') 
      time.sleep(5) 
      continue 
     j = json.loads(response) 
     if j['results']: 
      text = j['results'][0]['text'] 
      tID = j['results'][0]['id'] 
     else: 
      pprint('bad JSON') 
     if countTweet != 0 and lastID != tID: 
      pprint('new ID') 
      a.pin_mode(12, firmata.OUTPUT) #Gets stuck here 
      a.delay(2) 
      a.digital_write(12, firmata.HIGH) 
      a.delay(2) 
      a.digital_write(12, firmata.LOW) 
      pprint('done firmata') 
      lastID = tID 
      pprint (text) 
      pprint ('1') 
     else: 
      pprint("FLC") #First loop complete: To gather the existing tweet before we start 
      lastID = tID 
      countTweet += 1 
     time.sleep(15) 

我該如何構建這個腳本,以便Firmata/Serial在每個循環上都能工作? 我很想知道爲什麼上面的腳本根本不起作用,但是下面的LED例子會起作用。

from firmata import * 

a = Arduino('COM13') 
a.pin_mode(12, firmata.OUTPUT) 
a.delay(2) 

while True: 
    a.digital_write(12, firmata.HIGH) 
    a.delay(2) 
    a.digital_write(12, firmata.LOW) 
    a.delay(2) 

Arduino的運行oldStandardFirmata

#include <EEPROM.h> 
#include <Firmata.h> 

/*============================================================================== 
* GLOBAL VARIABLES 
*============================================================================*/ 

/* analog inputs */ 
int analogInputsToReport = 0; // bitwise array to store pin reporting 
int analogPin = 0; // counter for reading analog pins 

/* digital pins */ 
byte reportPINs[TOTAL_PORTS]; // PIN == input port 
byte previousPINs[TOTAL_PORTS]; // PIN == input port 
byte pinStatus[TOTAL_PINS]; // store pin status, default OUTPUT 
byte portStatus[TOTAL_PORTS]; 

/* timer variables */ 
unsigned long currentMillis;  // store the current value from millis() 
unsigned long previousMillis; // for comparison with currentMillis 


/*============================================================================== 
* FUNCTIONS                 
*============================================================================*/ 

void outputPort(byte portNumber, byte portValue) 
{ 
    portValue = portValue &~ portStatus[portNumber]; 
    if(previousPINs[portNumber] != portValue) { 
     Firmata.sendDigitalPort(portNumber, portValue); 
     previousPINs[portNumber] = portValue; 
     Firmata.sendDigitalPort(portNumber, portValue); 
    } 
} 

/* ----------------------------------------------------------------------------- 
* check all the active digital inputs for change of state, then add any events 
* to the Serial output queue using Serial.print() */ 
void checkDigitalInputs(void) 
{ 
    byte i, tmp; 
    for(i=0; i < TOTAL_PORTS; i++) { 
     if(reportPINs[i]) { 
      switch(i) { 
      case 0: outputPort(0, PIND &~ B00000011); break; // ignore Rx/Tx 0/1 
      case 1: outputPort(1, PINB); break; 
      case 2: outputPort(2, PINC); break; 
      } 
     } 
    } 
} 

// ----------------------------------------------------------------------------- 
/* sets the pin mode to the correct state and sets the relevant bits in the 
* two bit-arrays that track Digital I/O and PWM status 
*/ 
void setPinModeCallback(byte pin, int mode) { 
    byte port = 0; 
    byte offset = 0; 

    if (pin < 8) { 
     port = 0; 
     offset = 0; 
    } else if (pin < 14) { 
     port = 1; 
     offset = 8;  
    } else if (pin < 22) { 
     port = 2; 
     offset = 14; 
    } 

    if(pin > 1) { // ignore RxTx (pins 0 and 1) 
     pinStatus[pin] = mode; 
     switch(mode) { 
     case INPUT: 
      pinMode(pin, INPUT); 
      portStatus[port] = portStatus[port] &~ (1 << (pin - offset)); 
      break; 
     case OUTPUT: 
      digitalWrite(pin, LOW); // disable PWM 
     case PWM: 
      pinMode(pin, OUTPUT); 
      portStatus[port] = portStatus[port] | (1 << (pin - offset)); 
      break; 
     //case ANALOG: // TODO figure this out 
     default: 
      Firmata.sendString(""); 
     } 
     // TODO: save status to EEPROM here, if changed 
    } 
} 

void analogWriteCallback(byte pin, int value) 
{ 
    setPinModeCallback(pin,PWM); 
    analogWrite(pin, value); 
} 

void digitalWriteCallback(byte port, int value) 
{ 
    switch(port) { 
    case 0: // pins 2-7 (don't change Rx/Tx, pins 0 and 1) 
     // 0xFF03 == B1111111100000011 0x03 == B00000011 
     PORTD = (value &~ 0xFF03) | (PORTD & 0x03); 
     break; 
    case 1: // pins 8-13 (14,15 are disabled for the crystal) 
     PORTB = (byte)value; 
     break; 
    case 2: // analog pins used as digital 
     PORTC = (byte)value; 
     break; 
    } 
} 

// ----------------------------------------------------------------------------- 
/* sets bits in a bit array (int) to toggle the reporting of the analogIns 
*/ 
//void FirmataClass::setAnalogPinReporting(byte pin, byte state) { 
//} 
void reportAnalogCallback(byte pin, int value) 
{ 
    if(value == 0) { 
     analogInputsToReport = analogInputsToReport &~ (1 << pin); 
    } 
    else { // everything but 0 enables reporting of that pin 
     analogInputsToReport = analogInputsToReport | (1 << pin); 
    } 
    // TODO: save status to EEPROM here, if changed 
} 

void reportDigitalCallback(byte port, int value) 
{ 
    reportPINs[port] = (byte)value; 
    if(port == 2) // turn off analog reporting when used as digital 
     analogInputsToReport = 0; 
} 

/*============================================================================== 
* SETUP() 
*============================================================================*/ 
void setup() 
{ 
    byte i; 

    Firmata.setFirmwareVersion(2, 0); 

    Firmata.attach(ANALOG_MESSAGE, analogWriteCallback); 
    Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback); 
    Firmata.attach(REPORT_ANALOG, reportAnalogCallback); 
    Firmata.attach(REPORT_DIGITAL, reportDigitalCallback); 
    Firmata.attach(SET_PIN_MODE, setPinModeCallback); 

    portStatus[0] = B00000011; // ignore Tx/RX pins 
    portStatus[1] = B11000000; // ignore 14/15 pins 
    portStatus[2] = B00000000; 

// for(i=0; i<TOTAL_PINS; ++i) { // TODO make this work with analogs 
    for(i=0; i<14; ++i) { 
     setPinModeCallback(i,OUTPUT); 
    } 
    // set all outputs to 0 to make sure internal pull-up resistors are off 
    PORTB = 0; // pins 8-15 
    PORTC = 0; // analog port 
    PORTD = 0; // pins 0-7 

    // TODO rethink the init, perhaps it should report analog on default 
    for(i=0; i<TOTAL_PORTS; ++i) { 
     reportPINs[i] = false; 
    } 
    // TODO: load state from EEPROM here 

    /* send digital inputs here, if enabled, to set the initial state on the 
    * host computer, since once in the loop(), this firmware will only send 
    * digital data on change. */ 
    if(reportPINs[0]) outputPort(0, PIND &~ B00000011); // ignore Rx/Tx 0/1 
    if(reportPINs[1]) outputPort(1, PINB); 
    if(reportPINs[2]) outputPort(2, PINC); 

    Firmata.begin(115200); 
} 

/*============================================================================== 
* LOOP() 
*============================================================================*/ 
void loop() 
{ 
/* DIGITALREAD - as fast as possible, check for changes and output them to the 
* FTDI buffer using Serial.print() */ 
    checkDigitalInputs(); 
    currentMillis = millis(); 
    if(currentMillis - previousMillis > 20) { 
     previousMillis += 20;  // run this every 20ms 
     /* SERIALREAD - Serial.read() uses a 128 byte circular buffer, so handle 
     * all serialReads at once, i.e. empty the buffer */ 
     while(Firmata.available()) 
      Firmata.processInput(); 
     /* SEND FTDI WRITE BUFFER - make sure that the FTDI buffer doesn't go over 
     * 60 bytes. use a timer to sending an event character every 4 ms to 
     * trigger the buffer to dump. */ 

     /* ANALOGREAD - right after the event character, do all of the 
     * analogReads(). These only need to be done every 4ms. */ 
     for(analogPin=0;analogPin<TOTAL_ANALOG_PINS;analogPin++) { 
      if(analogInputsToReport & (1 << analogPin)) { 
       Firmata.sendAnalog(analogPin, analogRead(analogPin)); 
      } 
     } 
    } 
} 

回答

1

我的印象中,你的串行通信Arduino是行不通的。我看不到在哪裏以及如何打開串口和端口參數。您的程序卡在嘗試與串口通信的第一行。

import serial 
    ser = serial.Serial() 
    ser.port = "/dev/ttyUSB0" # may be called something different 
    ser.baudrate = 115200 # may be different 
    ser.open() 
+0

請張貼Arduino代碼。你有沒有發現串口通信是否正常工作?請告訴我。 – FeliceM 2013-04-29 15:42:33

+0

已發佈。這是與蟒鬆圖書館合作的建議冷漠素描。這是我沒有得到的,它適用於較短的草圖。儘管如此,它似乎打破了。 Arduino上的TX LED似乎從一個非常快的脈衝(工作)變成了一個恆定的高(斷開)。 – Hooperstu 2013-04-30 09:41:23

+1

這真是一個謎......我可以給你的唯一建議是確保你使用的是最後一個版本的處理庫。谷歌搜索我發現,有幾個人經歷了更新庫後消失的同樣的問題。 – FeliceM 2013-05-01 15:49:35