I'm working on a project with the SK Pang/ SparkFun Canbus shield (http://skpang.co.uk/catalog/arduino-canbus-shield-with-usd-card-holder-p-706.html) which has inputs/outputs for the CAN bus, a Serial LCD, GPS, and uSD card. I'm trying to create a sketch that will take the engine data, perform calculations on it, output the calculated data to the LCD, pair it with GPS data, and write that to the uSD card. When I try to operate the LCD, GPS, and uSD all at the same time, the uSD card does not receive output. However, combinations of the LCD/GPS and GPS/uSD work.
Here's my basic code for logging and displaying GPS data only, which I'm including because it has pin setups for the SoftwareSerial objects:
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <SD.h>
SoftwareSerial sLCD = SoftwareSerial(3, 6);
TinyGPSPlus gps;
SoftwareSerial ss(4, 3); //pins for the GPS
const int chipSelect = 9;
void setup()
{
Serial.begin(115200); //for the serial output
ss.begin(4800); //start ss at 4800 baud
sLCD.begin(9600);
sLCD.write("gpslogger");
//Serial.println("gpsLogger by Aaron McRuer");
//Serial.println("based on code by Mikal Hart");
//Serial.println();
pinMode(10, OUTPUT);
if(!SD.begin(chipSelect))
{
Serial.println("Card failed, or not present.");
return;
}
Serial.println("Card initialized.");
}
void loop()
{
clearLCD();
cursorHome();
sLCD.write("Opening file.");
File dataFile = SD.open("WRITE07.TXT", FILE_WRITE);
delay(2000);
clearLCD();
cursorHome();
sLCD.write("File opened.");
delay(2000);
clearLCD();
bool newData = false;
//For one second we parse GPS data and report some key values
for (unsigned long start = millis(); millis() - start < 1000;)
{
while (ss.available())
{
char c = ss.read();
Serial.write(c); //uncomment this line if you want to see the GPS data flowing
if(gps.encode(c)) //did a new valid sentence come in?
newData = true;
}
}
if(newData)
{
dataFile.print("Lat: ");
dataFile.print(gps.location.lat(), 6);
dataFile.print("\n");
dataFile.print("Lng: ");
dataFile.print(gps.location.lng(), 6);
dataFile.print("\n");
}
dataFile.close();
}
void clearLCD(){
sLCD.write(12);
}
void cursorHome(){
sLCD.write(254);
sLCD.write(128);
}
Given the specs on the website (schematics, etc.) and what's known about the Uno R3, is it possible to use all three add-ons (the uSD card, GPS transceiver, and serial LCD) at the same time? If it is, how so, and is it something I'm doing wrong with my code?
With data logging, I think you are more likely to run out of memory before you run out of pins.
Pin 4 is usually used by the SD but I see you are using it for the GPS with software serial. It may be possible to do this by ensuring that the SD is closed when the GPS is operational, but I don't know why you don't use the standard hardware serial - apparently you don't use it at all.
I recognise that you are obliged to use software serial somewhere, and I sympathise with your suffering, but you need to be aware of its limitations, and I submit you should only use it as a last resort..
The main gist is that I believe you are unwittingly using pin 4 for the SD and are definitely using pin 4 for the GPS, as in
SoftwareSerial ss(4, 3); //pins for the GPS
i.e., a clash of pins. So the idea is to resolve the clash by getting the GPS off pin 4 and leave it to the SD card in the normal manner. Further, the proper hardware serial pins 0 and 1 seem to be conspicuously under-employed.
I have successfully avoided even the prospect of using software serial so I'm guessing a bit, but I think you might consider putting the LCD on hardware serial, as you say, and the GPS where LCD came from. I say this because the serial monitor shares hardware serial and having the display there is less likely to be a problem.
You may find there are other software serial options that will solve the problem anyway. Just be aware of the limitations.
I think you are probably running out of memory. I've tried a similar thing, running a GPS, SD card, and a 7-segment LED display. Any two would work. When I used all three it would behave strangely, rebooting itself sometimes. The problem was that the Arduino was running out of memory. I ended up re-writing the display and GPS libraries to cut out some of the features I didn't need. The SD library was more complicated so I didn't touch that.
Now I'm trying to build a similar project, using an Uno R3, GPS/SD logging shield from Adafruit, and a Nokia LCD display, and I'm running into the same problem. The Nokia LCD display doesn't have its own buffer so it all has to be buffered in the Arduino. At the moment I've not been able to get it trimmed down small enough. If anyone has a very light-weight SD library, that would be great.
astronomerdave:
I think you are probably running out of memory. I've tried a similar thing, running a GPS, SD card, and a 7-segment LED display. Any two would work. When I used all three it would behave strangely, rebooting itself sometimes. The problem was that the Arduino was running out of memory. I ended up re-writing the display and GPS libraries to cut out some of the features I didn't need. The SD library was more complicated so I didn't touch that.
Now I'm trying to build a similar project, using an Uno R3, GPS/SD logging shield from Adafruit, and a Nokia LCD display, and I'm running into the same problem. The Nokia LCD display doesn't have its own buffer so it all has to be buffered in the Arduino. At the moment I've not been able to get it trimmed down small enough. If anyone has a very light-weight SD library, that would be great.
Do you think the Arduino Mega 2560 would work?
This is basically a do-or-die situation for me. It's my "final" project for my college degree. I know that there's a problem (and possibly the reason why), but I just can't find the solution. If there's not enough serial ports on the board to run all of them at the same time, then I need a solution to that. If there's a problem with pins being shared, I need a solution to that, because I'm not sure how to tell if pins are being shared.
Power supply is not immaterial - Uno only has 150mA regulator for 3.3V power, and SD cards need much more than that. Is the SD making it's own 3.3V from the Uno 5V?
How much current does the LCD need for its backlighting?
I'm not familiar with the libraries being used. Isn't this saying pin 3 is being used twice?
SoftwareSerial sLCD = SoftwareSerial(3, 6);
TinyGPSPlus gps;
SoftwareSerial ss(4, 3); //pins for the GPS
Nerdenator:
Do you think the Arduino Mega 2560 would work?
This is basically a do-or-die situation for me. It's my "final" project for my college degree. I know that there's a problem (and possibly the reason why), but I just can't find the solution. If there's not enough serial ports on the board to run all of them at the same time, then I need a solution to that. If there's a problem with pins being shared, I need a solution to that, because I'm not sure how to tell if pins are being shared.
All you need to know is what devices require what pins, and where you actually plug them in. It's you that is doing the nominating and the plugging. The only time there can be a misunderstanding, and even that shouldn't happen with a final project, is where a device is included on the main board, or is part of a shield, hence the matter of the SD. Moving to a Mega can only fix the problem insofar as that it offers four hardware serial ports. I recall that your problem may be a clash between SD and GPS, hence moving to a Mega may fix it by having the GPS on hardware serial, but you may find you can do this just with a better choice of software serial. I don't know anything about GPS. If the comms is only one-way, using software serial could be a better idea.
As I said, you are likely to run out of memory with this sort of project before you run out of pins, in which case moving to a Mega would be the solution. If you have really ballsed it up on the memory front, the IDE will refuse to compile, and tell you in plain English. The IDE also tells you how much memory was used for a successful compile but, when you are close to the edge, a successful compile does not guarantee a successful run. So, while a Uno is ostensibly good for 32k, a successful compile at 31k, or even 30k, is a pretty good signal that it's time to move.
CrossRoads:
I'm not familiar with the libraries being used. Isn't this saying pin 3 is being used twice?
SoftwareSerial sLCD = SoftwareSerial(3, 6);
TinyGPSPlus gps;
SoftwareSerial ss(4, 3); //pins for the GPS
It wouldn't explode since the Arduino only TX's to the LCD and RXs from the GPS. But the Arduino Cookbook would recommend you use "255" for the unneeded pin.
I'm going to try the angle dealing with the pin duplication problem first. Unfortunately, my LCD burned out, but I'll have a new one by tomorrow (hopefully).
Looking at the schematic for the Arduino relating to the outputs of the CAN-bus shield itself, I find that the SD card relies on pin 9. The LCD relies on pin 6, and the GPS doesn't seem to be directly mapped to any particular pins. There are only three "open" pins on the schematic, those being pins 3-5.
The schematic is attached. Am I interpreting this correctly? If so, would I just need to shift what I define the pins as?
Why do you not just "off-load" the entire SD write process? You are only logging the results to SD, not reading the card. You can simplify your software architecture, return over 25% SRAM to the main uC not to mention the returned bandwidth.
9600 BAUD continuous SD recording can be done easily at 8MHz which means just a naked atmega328P-PU for between $2 and $3 ... No boot loader required. My prototype builds: http://forum.arduino.cc/index.php?topic=154864.0