当使用此脚本使 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));
}
}
}
}