Hello to all.
I try to call a function inside a cpp file called from a h file that I include in my sketch. It returns a buffer[] and then try to write it to a file in the SD card. Then I get a sync failed error message from the sdfat lib. I comment the function in question and I get it right without data that i should had ofcourse as i commented the call and no sync failed error :-?
What does it provoke the sync failed error?
Here is the code
void loop(void) {
// clear print error
file.writeError = 0;
delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));
Canbus.ecu_req(ENGINE_RPM,buffer) // Request for engine RPM
file.print(buffer); // Write data to file
file.print(",");
Serial.print(buffer); // Send data to serial monitor
Serial.print(",");
if ((millis() - syncTime) < SYNC_INTERVAL) return;
syncTime = millis();
if (!file.sync()) error("sync failed");
}
And this is what the Canbus.ecu_req(ENGINE_RPM,buffer) looks like
Some questions arise
Where did you allocate buffer? how big is it?
As a sdcard is a persistant filesystem it should be handled carefully. Your code opens the file in setup() I assume but it never closes. So if you have a restart of your sketch the filehandles / admin on the sdcard could be corrupted. that might be the cause.
This can be prevented (99.9%) by doing the fileIO in a separate function that opens the file and closes it again every time its called. Only when the Arduino is stopped (or the SDcard is removed) in the middle of a write the SDcard can be corrupted. In one of my sketches I have a LED added as a "drivelight" like the floppydrives used to have so I can see when the SDcard is used. If you want to make it more robust you could add a switch that enables/disables writing to the SDcard. start stop logging switch.
Another cause can be a "bad" SDcard. DO you have the same problem with all your SDcards?
Buffer is allocated in the beginning of the sketch.
What you say is true but it is very weird that the code works without calling the Canbus.ecu_req function and logs commas in this case , but when I call the function says sync error.
I looked up in the Class Reference guide of the sdfat library and saw that Reasons for failure include a call to sync() before a file has been opened or an I/O error.
Then I kept commenting out code from the Canbus.ecu_req function to see what causes the error and saw that this mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0); is causing the error.
The SPI stuff reminded me about a D10 pin that has to be set as output and then set it HIGH in the loop function. I saw that in the example sketch for the FAT16 lib.
I made the changes in the code but still the same.
No experience with CAN bus but the line RESET(MCP2515_CS); triggered me. Can it be that it also resets the SDcard or so as both are on the SPI bus?
The failing sync is probably only the last is a chain of errors, and most visible.
Could you try the following:
disable the CANbus stuff and create dummy functions for them that create some reasonable output in buffer. This way we exclude the CAN hardware. Try to store the buffer to the SDcard again.
If this works the problems are likely be caused by the CAN bus e.g. interference between the CAN bus and the SDCArd (both on SPI-bus)
If it doesn't work the problems are to be searched in the SDcard lib.
No need for big changes in the code.. if I comment the line in question it won't access the SPI stuff so it won't throw an error.
I aggree with the "both on SPI bus" thing you said ...
How can I over pass it though ... Can I control the access to the SPI and have CANbus and sdcard have turns to access it ?
No SPI expert either but both CANBUS and SDcard should have one pin called Slave Select (SS) that should be a different pin for both. The other three pins can be shared.
You need to add some code to toggle them, could look something like this below (not compiled or tested, just to get an idea)
#define SDSS 8 // the SS pin of the SDCard
#define CANSS 9 // the SS pin of the CAN shield
digitalWrite(SDSS, HIGH);
// access the SDCARD
digitalWrite(SDSS, LOW );
digitalWrite(CANSS, HIGH);
// access the CAN bus
digitalWrite(CANSS, LOW);
I looked in the CANBUS shield shematics to see the Chip Select pins of the CANBUS reader and the SD, then set them as outputs in the setup() function and finaly set the SD card off , set the CAN on , read the CANBUS, set the CAN off and set the SD on ... and it worked .... ;D
here is the parts of the code I added ...
int CANCS = 10; //MCP2515 Chip Select pin
int SDCS = 9; //uSDcard Chip Select pin
Then in setup() i added these two lines ...
pinMode(SDCS, OUTPUT);
pinMode(CANCS, OUTPUT);
And then change the loop() like this ...
digitalWrite(SDCS, HIGH); //Chips are selected when setting them low
digitalWrite(CANCS, LOW);
Canbus.ecu_req(ENGINE_RPM,buffer); // Request for engine RPM
digitalWrite(CANCS, HIGH);
digitalWrite(SDCS, LOW);
file.writeError = 0;
file.print(reading);
file.print(",");
file.println(buffer);
thanks for sharing the working code. Maybe if the whole application works you could write an article about it on the playground? To learn people about the CAN bus.
Sure thing. I just need the time and lots of trials and errors to have a complete working solution. It is a promise though that when complete it will have its place in the playground.