How to use SofwareSerial library to connect a Serial GPS on the Official Arduino Robot?
We have chosen for our robot this excellent "Ultimate GPS" module from Adafruit, because it requires only 2 pins (using serial communication) to communicate with and it's plenty of good functionality (autonomous GPS logger, Time RTC, energy safer...).
Wiring
Due to lack of memory on the Control Board, we've decided to connect the GPS to the Motor board.
2 digital pin included one using interrupts are required to connect the GPS to the Motor Board.
We decide to connect the TX pin of the GPS to the SPI/ICSP connector on MOSI pin because it's a Digital pin with interrupt management and connector was not used on this board.
The RX pin of the GPS must be connected to another digital pin, we choose TK3 (B_TK3 on the picture)
Coding
You have to include the SoftwareSerial library to your project but with Arduino IDE 1.5.4 some core arduino header files must be patched to be able to compile.
You have to add these 4 definition (digitalPinToPCICR, digitalPinToPCICRbit, digitalPinToPCMSK, digitalPinToPCMSKbit(p) ) into the pin_arduino.h file in these following directories:
- ...\Arduino\hardware\arduino\avr\variants\robot_control
- ...\Arduino\hardware\arduino\avr\variants\robot_motor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define digitalPinToPCICR(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCICR) : ((uint8_t *)0)) | |
#define digitalPinToPCICRbit(p) 0 | |
#define digitalPinToPCMSK(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCMSK0) : ((uint8_t *)0)) | |
#define digitalPinToPCMSKbit(p) ( ((p) >= 8 && (p) <= 11) ? (p) - 4 : ((p) == 14 ? 3 : ((p) == 15 ? 1 : ((p) == 16 ? 2 : ((p) == 17 ? 0 : (p - A8 + 4)))))) | |
// __AVR_ATmega32U4__ has an unusual mapping of pins to channels | |
extern const uint8_t PROGMEM analog_pin_to_channel_PGM[]; | |
#define analogPinToChannel(P) ( pgm_read_byte( analog_pin_to_channel_PGM + (P) ) ) |
Command on the Control Board
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Used to convert Bytes to float | |
union float2bytes { float f; char b[sizeof(float)]; }; | |
// Read GPS coordinate from the Motor Board | |
void RobotControl::readGPSCoord(GPS_DATA &gpsData){ | |
messageOut.writeByte(COMMAND_READ_GPS_COORD); | |
messageOut.sendData(); | |
delay(10); | |
while(!messageIn.receiveData()); | |
uint8_t mess = messageIn.readByte(); | |
if(mess==COMMAND_READ_GPS_COORD_RE){ | |
gpsData.fix = messageIn.readByte(); | |
gpsData.sat = messageIn.readByte(); | |
float2bytes f2b; | |
uint8_t i; | |
for ( i=0; i < 4; i++ ) | |
f2b.b[i] = messageIn.readByte(); | |
gpsData.lat = f2b.f; | |
for ( i=0; i < 4; i++ ) | |
f2b.b[i] = messageIn.readByte(); | |
gpsData.lon = f2b.f; | |
for ( i=0; i < 4; i++ ) | |
f2b.b[i] = messageIn.readByte(); | |
gpsData.alt = f2b.f; | |
} | |
} |
Response on the Motor Board
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void RobotMotorBoard::parseCommand(){ | |
uint8_t modeName; | |
uint8_t codename; | |
//... | |
if(this->messageIn.receiveData()){ | |
//Serial.println("data received"); | |
uint8_t command=messageIn.readByte(); | |
//Serial.println(command); | |
switch(command){ | |
//... | |
case COMMAND_READ_GPS_COORD: | |
_readGPSCoord(); | |
break; | |
//... | |
} | |
} | |
} | |
// Used to convert Bytes to float | |
union float2bytes { float f; char b[sizeof(float)]; }; | |
// Send GPS coordinate to the Control Board | |
void RobotMotorBoard::_readGPSCoord(){ | |
messageOut.writeByte(COMMAND_READ_GPS_COORD_RE); | |
messageOut.writeByte(GPS.fix); | |
messageOut.writeByte(GPS.satellites); | |
float2bytes f2b; | |
uint8_t i; | |
f2b.f = GPS.latitude; | |
for ( i=0; i < sizeof(float); i++ ) | |
messageOut.writeByte(f2b.b[i]); | |
f2b.f = GPS.longitude; | |
for ( i=0; i < sizeof(float); i++ ) | |
messageOut.writeByte(f2b.b[i]); | |
f2b.f = GPS.altitude; | |
for ( i=0; i < sizeof(float); i++ ) | |
messageOut.writeByte(f2b.b[i]); | |
messageOut.sendData(); | |
} |
GPS Management has been coded without interrupt due to problem using Interrupt, SoftwareSerial library and Serial.print() function (I still not not have answer for this trouble, any idea?).
How to well understand the GPS information received?
According to the GPS, a location as 4042.6142,N (Latitude 40 degrees, 42.6142 decimal minutes North) & 07400.4168,W. (Longitude 74 degrees, 0.4168 decimal minutes West) To look at this location in Google maps, type +40° 42.6142', -74° 00.4168' into the google maps search box . Unfortunately gmaps requires you to use +/- instead of NSWE notation. N and E are positive, S and W are negative. The code has been adapted in consequence.

No comments:
Post a Comment