2015-04-22 36 views
0

所以我有這個項目。如果緊急車輛靠近交通信號燈並且靠近時,系統會優先考慮緊急車輛,我希望將交通信號燈的狀態從紅色變爲綠色,但順序正確。交通燈模擬和xbee通訊

我已經設法將其關閉,但它不適用於真正的汽車,因爲xbees(自行設置的交通信號燈上的車輛和終端設備上的協調器)需要一些時間進行通信,這對於速度來說是不夠的車輛接近交通燈可以說平均時速60公里/小時。

該系統的工作原理是這樣的。車上有一個arduino,它有一個GPS護罩和一個xbee設置在它的COORDINATOR上。在arduino的程序中,它檢查gps是否讀取保存在arduino內部的座標,以便檢查實時座標,如果它們匹配,則xbee會發送一條消息到對應的xbees,這些xbees被設置爲終端設備在再次設置的紅綠燈上是arduino + xbee。

問題1是我需要(協調員 - 終端設備)的xbees之間更快的連接

這裏是Arduino的GPS協調員Arduino的草圖。注意:GPS盾牌來自adafruit,我使用他們的代碼加上我的一些。

// Test code for Adafruit GPS modules using MTK3329/MTK3339 driver 
// 
// This code shows how to listen to the GPS module in an interrupt 
// which allows the program to have more 'freedom' - just parse 
// when a new NMEA sentence is available! Then access data when 
// desired. 
// 
// Tested and works great with the Adafruit Ultimate GPS module 
// using MTK33x9 chipset 
// ------> http://www.adafruit.com/products/746 
// Pick one up today at the Adafruit electronics shop 
// and help support open source hardware & software! -ada 

#include <Adafruit_GPS.h> 
#include <SoftwareSerial.h> 

SoftwareSerial mySerial(10, 11); 
SoftwareSerial xbee(13,12); 

// If using hardware serial (e.g. Arduino Mega), comment out the 
// above SoftwareSerial line, and enable this line instead 
// (you can change the Serial number to match your wiring): 

//HardwareSerial mySerial = Serial1; 


Adafruit_GPS GPS(&mySerial); 


// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console 
// Set to 'true' if you want to debug and listen to the raw GPS sentences. 
#define GPSECHO true 

// this keeps track of whether we're using the interrupt 
// off by default! 
boolean usingInterrupt = false; 
void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy 

void setup() 
{ 

    Serial.begin(115200); 
    Serial.println("Adafruit GPS library basic test!"); 
    xbee.begin(9600); 
    xbee.println("SoftwareSerial on coordinator working!"); 
    GPS.begin(9600); 

    // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude 
    GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); 
    // uncomment this line to turn on only the "minimum recommended" data 
    //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY); 
    // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since 
    // the parser doesn't care about other sentences at this time 

    // Set the update rate 
    GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate 
    // For the parsing code to work nicely and have time to sort thru the data, and 
    // print it out we don't suggest using anything higher than 1 Hz 

    // Request updates on antenna status, comment out to keep quiet 
    GPS.sendCommand(PGCMD_ANTENNA); 

    // the nice thing about this code is you can have a timer0 interrupt go off 
    // every 1 millisecond, and read data from the GPS for you. that makes the 
    // loop code a heck of a lot easier! 
    useInterrupt(true); 

    delay(1000); 
    // Ask for firmware version 
    mySerial.println(PMTK_Q_RELEASE); 
} 


// Interrupt is called once a millisecond, looks for any new GPS data, and stores it 
SIGNAL(TIMER0_COMPA_vect) { 
    char c = GPS.read(); 
    // if you want to debug, this is a good time to do it! 
#ifdef UDR0 
    if (GPSECHO) 
    if (c) UDR0 = c; 
    // writing direct to UDR0 is much much faster than Serial.print 
    // but only one character can be written at a time. 
#endif 
} 

void useInterrupt(boolean v) { 
    if (v) { 
    // Timer0 is already used for millis() - we'll just interrupt somewhere 
    // in the middle and call the "Compare A" function above 
    OCR0A = 0xAF; 
    TIMSK0 |= _BV(OCIE0A); 
    usingInterrupt = true; 
    } else { 
    // do not call the interrupt function COMPA anymore 
    TIMSK0 &= ~_BV(OCIE0A); 
    usingInterrupt = false; 
    } 
} 

// difference_ratio 
float diff_ratio = 0.010; 

// COORDINATES INDEX 
float coord_lat = 23; 
float coord_lon = 23; 

uint32_t timer = millis(); 
void loop()      // run over and over again 
{ 
    // in case you are not using the interrupt above, you'll 
    // need to 'hand query' the GPS, not suggested :(
    if (! usingInterrupt) { 
    // read data from the GPS in the 'main loop' 
    char c = GPS.read(); 
    // if you want to debug, this is a good time to do it! 
    if (GPSECHO) 
     if (c) Serial.print(c); 
    } 

    // if a sentence is received, we can check the checksum, parse it... 
    if (GPS.newNMEAreceived()) { 
    // a tricky thing here is if we print the NMEA sentence, or data 
    // we end up not listening and catching other sentences! 
    // so be very wary if using OUTPUT_ALLDATA and trytng to print out data 
    //Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false 

    if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false 
     return; // we can fail to parse a sentence in which case we should just wait for another 
    } 

    // if millis() or timer wraps around, we'll just reset it 
    if (timer > millis()) timer = millis(); 

    // approximately every 2 seconds or so, print out the current stats 
    if (millis() - timer > 2000) { 
    timer = millis(); // reset the timer 

    Serial.print("\nTime: "); 
    Serial.print(GPS.hour, DEC); Serial.print(':'); 
    Serial.print(GPS.minute, DEC); Serial.print(':'); 
    Serial.print(GPS.seconds, DEC); Serial.print('.'); 
    Serial.println(GPS.milliseconds); 
    Serial.print("Date: "); 
    Serial.print(GPS.day, DEC); Serial.print('/'); 
    Serial.print(GPS.month, DEC); Serial.print("/20"); 
    Serial.println(GPS.year, DEC); 
    Serial.print("Fix: "); Serial.print((int)GPS.fix); 
    Serial.print(" quality: "); Serial.println((int)GPS.fixquality); 


    if (GPS.fix) { 
     //Serial.print("Location: "); 
     //Serial.print(GPS.latitude, 4); Serial.print(GPS.lat); 
     //Serial.print(", "); 
     //Serial.print(GPS.longitude, 4); Serial.println(GPS.lon); 
     Serial.print("Location (in degrees, works with Google Maps): "); 
     Serial.print(GPS.latitudeDegrees, 4); 
     Serial.print(", "); 
     Serial.println(GPS.longitudeDegrees, 4); 

     //Serial.print("Speed (knots): "); Serial.println(GPS.speed); 
     //Serial.print("Angle: "); Serial.println(GPS.angle); 
     //Serial.print("Altitude: "); Serial.println(GPS.altitude); 
     //Serial.print("Satellites: "); Serial.println((int)GPS.satellites); 
     if(GPS.latitudeDegrees + diff_ratio >= coord_lat && coord_lat >= GPS.latitudeDegrees - diff_ratio) { 
     if(GPS.longitudeDegrees + diff_ratio >= coord_lon && coord_lon >= GPS.longitudeDegrees - diff_ratio){ 
      Serial.println("location OKAY"); 
      xbee.println("K"); 
     } 
     } 

     //if((float)GPS.latitude > (home_lat - diff_ratio) && (float) 
    } 
    } 
} 

重要的部分是它說if(GPS.fix())和以後的地方。

這裏是交通燈模擬的草圖,如果它接收到消息「K」,它將保持綠燈直到它不再接收它。

#include <SoftwareSerial.h> 

SoftwareSerial xbee(3,2); 

int greenled = 8; //Led's and pins 
int yellowled = 9; 
int redled = 10; 
int ard_led = 13; 

void setup(){ 
    pinMode(greenled,OUTPUT); 
    pinMode(yellowled, OUTPUT); 
    pinMode(redled, OUTPUT); 
    pinMode(ard_led,OUTPUT); 

    Serial.begin(9600); 
    xbee.begin(9600); 
} 

void loop(){ 

     delay(700); 

     if(xbee.available() > 0 && xbee.read() == 'K' && digitalRead(ard_led) == 0){ 

     //Serial.println("second block"); 
     digitalWrite(redled,HIGH); 
     delay(1000); 
     digitalWrite(yellowled, HIGH); //Yellow and red on for 2 seconds 
     digitalWrite(ard_led,HIGH); 

     }else if(xbee.available() > 0 && xbee.read() == 'K' && digitalRead(ard_led) == 1){ 
     //Serial.println("third block"); 
     blinking_green(); 

     } 

     else if(!xbee.available() && xbee.read() != 'K' && digitalRead(greenled) == 0){ 
     //Serial.println("first block"); 
     digitalWrite(redled, HIGH); 
     delay(1000); 
     digitalWrite(yellowled, HIGH); //Yellow and red on for 2 seconds 
     delay(1000); 
     digitalWrite(redled, LOW); //Red and Yellow off 
     digitalWrite(yellowled, LOW); 
     digitalWrite(greenled, HIGH); //Green on for 5 seconds 
     delay(3000); 
     digitalWrite(greenled, LOW); //Green off, yellow on for 2 seconds  
     digitalWrite(yellowled, HIGH); 
     delay(1000); 
     digitalWrite(yellowled,LOW); 
     digitalWrite(redled,HIGH); 


     } else if(!xbee.available() && xbee.read() != 'K' && digitalRead(greenled) == 1 && digitalRead(yellowled == 0)){ 
      //Serial.println("fourth block"); 
      digitalWrite(greenled,LOW); 
      digitalWrite(yellowled, HIGH); 
      delay(1000); 
      digitalWrite(yellowled, LOW); 
      digitalWrite(redled,HIGH); 
      digitalWrite(ard_led,LOW); 
     } 

} 

void blinking_green(){ 
    digitalWrite(redled, LOW); //Red and Yellow off 
    digitalWrite(yellowled, LOW); 
    digitalWrite(greenled,HIGH); 
    delay(2500); 


} 

問題2:我怎麼能瞬間中斷交通信號燈模擬時,從附近的Arduino交通燈變爲綠色之前完成這個循環會收到一條消息?因爲在一個實際的例子中,綠燈和紅燈會說超過20秒。

問題:xbee上的更快的波特率是否會實現更快的xbee通信?

預先感謝您

回答

1

您需要更改loop()你的交通燈模擬。有一個變量用於存儲燈的「狀態」,以及一個計時器來跟蹤下一個狀態改變發生的時間。這樣,您的循環也可以每次檢查XBee串行輸入。

if (xbee_event_happened()) { 
    set_leds_off(); 
    timer = millis(); 
    state = STATE_FLASH_GREEN_OFF; 
} 
switch (state) { 
    case STATE_FLASH_GREEN_OFF: 
     if (millis() - timer > 1000) { 
      set_leds_green(); 
      state = STATE_FLASH_GREEN_ON; 
      timer = millis(); 
     } 
     break; 
    case STATE_FLASH_GREEN_ON: 
     if (millis() - timer > 1000) { 
      set_leds_off(); 
      state = STATE_FLASH_GREEN_OFF; 
      timer = millis(); 
     } 
     break; 
    case STATE_RED: 
     if (millis() - timer > 5000) { 
      set_leds_green(); 
      state = STATE_GREEN; 
      timer = millis(); 
     } 
     break; 
    case STATE_GREEN: 
     if (millis() - timer > 3000) { 
      set_leds_yellow(); 
      state = STATE_YELLOW; 
      timer = millis(); 
     } 
     break; 
    // etc. 
} 

這只是涵蓋了基礎知識,但它顯​​示的loop()功能設計的一個重要方面 - 它不應該超過幾毫秒的時間運行。不要在主循環內部有延遲,跟蹤設備的狀態,然後使用邏輯來決定狀態是否需要在該循環過程中改變。

此外,使用更高的波特率時,能夠避免串行傳輸的延遲,在循環擺脫700毫秒的延遲,並組織你的if/else結構更好:

if (xbee.available() > 0) { 
    character = xbee.read(); 
    if (character == 'K') { 
     if (digitalRead(ard_led)) { 
     // second block 
     } else { 
     // third block 
     } 
    } else if (character == 'X') { 
     // do something different? Vehicle left area? 
    } 
    }