1

当使用此脚本使 pin12 上的 LED 闪烁时,脚本将不会越过 pin12 设置为高的 line27。没有错误信息。

    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));
            }
        }
    }
}
4

1 回答 1

1

我的印象是您与 arduino 的串行通信不起作用。我看不到您在何处以及如何打开串行端口和端口参数。您的程序卡在尝试与串行端口通信的第一行。

    import serial
    ser = serial.Serial()
    ser.port = "/dev/ttyUSB0" # may be called something different
    ser.baudrate = 115200 # may be different
    ser.open()
于 2013-04-28T13:59:41.720 回答