Okay, the sketch below is writing the header in the setup funtion, but none of the data is being written to the SD card. The serial output does show that there is data. Any thoughts?
// testing how quickly can poll the 3208 ADC
#include<SPI.h>
#include<LiquidCrystal.h>
#include <SdFat.h>
SdFat sd;
SdFile myFile;
const int chipSelect = 10;
int lcdpin = 9;
int adcpin = 2;
LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);
void setup() {
lcd.begin(16, 2);
Serial.begin(9600);
SPI.begin();
// Set the cable select for the ADC.
pinMode(adcpin, OUTPUT);
digitalWrite(adcpin, HIGH);
// Initialize SdFat or print a detailed error message and halt
// Use half speed like the native library.
// change to SPI_FULL_SPEED for more performance.
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();
// open the file for write at end like the Native SD library
if (!myFile.open("speed.csv", O_RDWR | O_CREAT | O_AT_END)) {
sd.errorHalt("opening speed.txt for write failed");
}
myFile.println("ADC,Time");
myFile.close();
}
void loop() {
int count;
unsigned long timelog[100];
int datalog[100];
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Ready");
delay(2000);
//for(int i = 0;1 < 3;i ++) {
for (int i = 0; i < 100; i ++) {
datalog[i] = adcpinread(7);
timelog[i] = micros();
}
lcd.clear();
lcd.setCursor(0,0);
lcd.print("counting done");
delay (3000);
if (!myFile.open("speed.csv", O_RDWR | O_CREAT | O_AT_END)) {
sd.errorHalt("opening test.txt for write failed");
lcd.setCursor(0,1);
lcd.print("Disk error:");
}
else {
lcd.setCursor(0,1);
lcd.print("test opened");
}
delay(3000);
for (int i = 0;i < 100; i ++) {
myFile.print(datalog[i]);
myFile.print(",");
myFile.println(timelog[i]);
Serial.print("ADC: ");
Serial.print(datalog[i]);
Serial.print(" Time: ");
Serial.println(timelog[i]);
}
//}
myFile.close();
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Done");
delay(50000);
}
int adcpinread(int channel)
{
int adcvalue = 0;
byte transbyte = 6;
byte returnbyte;
digitalWrite(adcpin, LOW); // Turn on device "adcpin"
// Set the first byte to transfer,
// with with a start bit and a 1 for single ended
// (not differentail) and the MSB of the channel number
if (channel >3) {
transbyte = 7;
}
SPI.transfer(transbyte);
// Set the next transfer byte with the channel number
// minus the MSB and catch the first 4 bits of the
// return value
transbyte |= (channel << 6);
returnbyte = SPI.transfer(transbyte);
// add the first four bits of the valuse to adcvalue
// then shift them to the first four (of 12) bits
adcvalue = returnbyte & 15;
adcvalue = adcvalue << 8;
// recieve the last 8 bits and add them to adc value
returnbyte = SPI.transfer(0x0);
adcvalue += returnbyte;
//end communication with device adcpin
digitalWrite(adcpin, HIGH);
return adcvalue;
}
SurferTim:
Which Arduino are you using? If it is an Uno, you can't use D13 for the lcd display. That is the SPI SCK pin.
It is an Uno, but SPI is a bus type interface. You can have several devices as long as they each have their own cable select pin. I am using SPI to talk to the SD shield, the LCD shield AND the 3208 ADC. It writes the header to the SD card, just not the data.
parrst:
I doubt that is the issue as the set up does write the header.
The setup is done before you write anything to the display, so that isn't conclusive. If you want to prove that it is nothing to do with the display, remove all the display code from your sketch and prove the SD write still doesn't work, then remove the display hardware and prove the SD write still doesn't work.
SurferTim:
Explain what part of the code writes the "header". Is it this?
myFile.println("ADC,Time");
Yes. And I did test and found that YES the LCD is conflicting with the SD. I am guessing that the header is writing okay since it is in the setup function not the loop. And there is nothing other than the lcd.begin in the setup.
I tried remocing mention of pin 13 in the LiquidCrystal command (Liquidcrystal can take the options without that number) and I even removed the shield and wired it up so that pin 13 was NOT connected. Only power, the 4 data pins at D4 - 8 and D8,9 for the RS and enable. the LCD works but the SD still does not. I really want to be able to use both of these shields. Any thoughts other than the $20 LCD that communicates via I2C?
parrst:
I doubt that is the issue as the set up does write the header.
The setup is done before you write anything to the display, so that isn't conclusive. If you want to prove that it is nothing to do with the display, remove all the display code from your sketch and prove the SD write still doesn't work, then remove the display hardware and prove the SD write still doesn't work.
Peter you are correct. I am now trying to find a way to make the two devices play nice. I got an LCD that used Pins D4 - 8 for data specifically so that it would work with the SD shield.
Okay, NOW I am really confused. In the code below, the SD gets written to in the setup function, but not in the loop function. ALL I have to do is comment out the LiquidCrystal include and it works. What is in the include that is messing it up?
// testing how quickly can poll the 3208 ADC
#include<SPI.h>
#include<LiquidCrystal.h>
#include <SdFat.h>
SdFat sd;
SdFile myFile;
const int chipSelect = 10;
int lcdpin = 9;
int adcpin = 2;
//LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
void setup() {
//lcd.begin(16, 2);
Serial.begin(9600);
SPI.begin();
// Set the cable select for the ADC.
pinMode(adcpin, OUTPUT);
digitalWrite(adcpin, HIGH);
// Initialize SdFat or print a detailed error message and halt
// Use half speed like the native library.
// change to SPI_FULL_SPEED for more performance.
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();
// open the file for write at end like the Native SD library
if (!myFile.open("speed.csv", O_RDWR | O_CREAT | O_AT_END)) {
sd.errorHalt("opening speed.txt for write failed");
}
myFile.println("ADC,Time");
myFile.close();
}
void loop() {
int count;
unsigned long timelog[100];
int datalog[100];
// lcd.clear();
// lcd.setCursor(0,0);
// lcd.print(" Ready");
delay(2000);
//for(int i = 0;1 < 3;i ++) {
for (int i = 0; i < 100; i ++) {
datalog[i] = adcpinread(7);
timelog[i] = micros();
delayMicroseconds(100);
}
// lcd.clear();
// lcd.setCursor(0,0);
// lcd.print("counting done");
// delay (3000);
if (!myFile.open("speed.csv", O_RDWR | O_CREAT | O_AT_END)) {
sd.errorHalt("opening test.txt for write failed");
//lcd.setCursor(0,1);
//lcd.print("Disk error:");
}
// else {
// lcd.setCursor(0,1);
// lcd.print("test opened");
// }
delay(3000);
for (int i = 0;i < 100; i ++) {
myFile.print(datalog[i]);
myFile.print(",");
myFile.println(timelog[i]);
Serial.print("ADC: ");
Serial.print(datalog[i]);
Serial.print(" Time: ");
Serial.println(timelog[i]);
}
//}
myFile.close();
/*lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Done");*/
delay(50000);
pinMode(3, OUTPUT);
digitalWrite(3, HIGH);
}
int adcpinread(int channel)
{
int adcvalue = 0;
byte transbyte = 6;
byte returnbyte;
digitalWrite(adcpin, LOW); // Turn on device "adcpin"
// Set the first byte to transfer,
// with with a start bit and a 1 for single ended
// (not differentail) and the MSB of the channel number
if (channel >3) {
transbyte = 7;
}
SPI.transfer(transbyte);
// Set the next transfer byte with the channel number
// minus the MSB and catch the first 4 bits of the
// return value
transbyte |= (channel << 6);
returnbyte = SPI.transfer(transbyte);
// add the first four bits of the valuse to adcvalue
// then shift them to the first four (of 12) bits
adcvalue = returnbyte & 15;
adcvalue = adcvalue << 8;
// recieve the last 8 bits and add them to adc value
returnbyte = SPI.transfer(0x0);
adcvalue += returnbyte;
//end communication with device adcpin
digitalWrite(adcpin, HIGH);
return adcvalue;
}
I didn't think this was the issue as the SD works if I remove/comment out all LCD code and the LCD works fine if I leave it in. But I did add the line you mentioned in my setup loop and it did not have any effect.
Something non-obvious is going on if adding/removing seemingly unrelated code changes behavior. Generally leads one to think of memory issues.
unsigned long timelog[100];
int datalog[100];
That's 600 bytes of of your 2048 bytes of RAM. Plus serial, plus LiquidCrystal, and plus SD, maybe you're running out of RAM.
For a test, drop your 100 elements (update your for-loops) down to 16 and see if that changes the behavior.
Also, wrap all of your strings in F() tags like this:
sd.errorHalt(F("opening speed.txt for write failed"));
Serial.print(F("ADC: "));
That'll keep them out of RAM. F() won't work on the myFile.open(), so don't use it there.
Also, what do you have going on here:
Around line 48
//for(int i = 0;1 < 3;i ++) {
for (int i = 0; i < 100; i ++) {
this looks like you were trying to nest a for() loop inside of another, but why are you using the same name for the increment variable? Is this included in the "lcd code" you comment out?
this looks like you were trying to nest a for() loop inside of another, but why are you using the same name for the increment variable? Is this included in the "lcd code" you comment out?
Good point. The outer loop was going to repeat the read from ADC then write to SD 3 times. I originally had the arrays set to 1000 but ran into memory issues. This was a work around and also a test to see how much time it took to write to SD.
I will try to lower the arrays and see if that helps.