As part of a university summer project I need to wirelessly transfer some data from one Arduino board with a microSD attached to another Arduino board with microSD. I have had success with the transmission side of things and have working code that can read text from a txt file and then transmit whatever is read. I know this code works fine as I have seen the transfer on the receiving serial monitor.
My problem is with the next stage - writing the received data to a microSD. I am using the Virtual Wire library for the wireless and SdFat for the storage. My code on the receiving Arduino is as follows:
//Attach receiver module facing outwards from pins 2 to 5 for no breadboard setup
#include <VirtualWire.h>
#include <SdFat.h>
//Virtual Wire initialisations
const int receive_pin = 3;
const int transmit_en_pin = 7;
const int Vpin = 2;
const int GND = 5;
//SdFat initialisations
SdFat sd;
SdFile myFile;
const int chipSelect = 4;
void setup()
{
delay(1000);
Serial.begin(9600); // Debugging only
Serial.println("setup");
// Initialise the IO and ISR
vw_set_rx_pin(receive_pin);
vw_set_ptt_pin(transmit_en_pin);
vw_set_ptt_inverted(true); // Required for DR3100
pinMode(Vpin, OUTPUT); // Sets up pins for use
pinMode(GND, OUTPUT);
digitalWrite(Vpin, HIGH); // Sets up pin voltage levels
digitalWrite(GND, LOW);
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) // Try to begin communication with microSD
sd.initErrorHalt(); // If fails then error
if (!myFile.open("rx.txt", O_RDWR | O_CREAT | O_AT_END)) // Try to open file for write
sd.errorHalt("opening rx.txt for write failed"); // If fails then error
vw_setup(2000); // Bits per sec
vw_rx_start(); // Start the receiver PLL running
}
void loop()
{
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)) // If a message is received...
{
for (int i = 0; i < buflen; i++) //For each received byte...
{
Serial.print((char)buf[i]);
myFile.println((char)buf[i]); //Write single byte to to myFile, rx.txt
}
myFile.close();
}
}
The problem is that received messages do not appear on the receiving serial monitor nor the receiving microSD (though the file "rx.txt" is created, it is just blank).
Is there some blaring misuse of the libraries here? I'm new to Arduinos but my transmission code is written in a similar way and works fine.
Any and all advice here would be appreciated and if I have missed out information then please ask. Thanks.
In your receiver code, you are opening myfile in setup();
and according to your code after receiving any data (vw_get_message(buf, &buflen)) it writes to file and close the myfile.
Now, once again when you receive any message you are not able to write to file because it is already closed.
so you need to reopen the file once you receive the data and after writing to file close it.
Hi Bijendra, moving both of the if statements and the file close to be within the for loop has got it writing!
The only problem now is that only the first array of bytes transferred gets written. I imagine that indicates that I have put something in the for loop that shouldn't be there?
Right now the code is:
//Attach receiver module facing outwards from pins 2 to 5 for no breadboard setup
#include <VirtualWire.h>
#include <SdFat.h>
//Virtual Wire initialisations
const int receive_pin = 3;
const int transmit_en_pin = 7;
const int Vpin = 2;
const int GND = 5;
//SdFat initialisations
SdFat sd;
SdFile myFile;
const int chipSelect = 4;
void setup()
{
delay(1000);
Serial.begin(9600); // Debugging only
Serial.println("setup");
// Initialise the IO and ISR
vw_set_rx_pin(receive_pin);
vw_set_ptt_pin(transmit_en_pin);
vw_set_ptt_inverted(true); // Required for DR3100
pinMode(Vpin, OUTPUT); // Sets up pins for use
pinMode(GND, OUTPUT);
digitalWrite(Vpin, HIGH); // Sets up pin voltage levels
digitalWrite(GND, LOW);
vw_setup(2000); // Bits per sec
vw_rx_start(); // Start the receiver PLL running
}
void loop()
{
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)) // If a message is received...
{
for (int i = 0; i < buflen; i++) //For each received byte...
{
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) // Try to begin communication with microSD
sd.initErrorHalt(); // If fails then error
if (!myFile.open("rx.txt", O_RDWR | O_CREAT | O_AT_END)) // Try to open file for write
sd.errorHalt("opening rx.txt for write failed"); // If fails then error
Serial.print((char)buf[i]);
myFile.println((char)buf[i]); //Write single byte to to myFile, rx.txt
myFile.close();
}
}
}
for (int i = 0; i < buflen; i++) //For each received byte...
{
// for every iteration you are initializing the the sd card, opening and closing the myfile.
// that might b creating a problem( i dont have sd card to test.)
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) // Try to begin communication with microSD
sd.initErrorHalt(); // If fails then error
if (!myFile.open("rx.txt", O_RDWR | O_CREAT | O_AT_END)) // Try to open file for write
sd.errorHalt("opening rx.txt for write failed"); // If fails then error
Serial.print((char)buf[i]);
myFile.println((char)buf[i]); //Write single byte to to myFile, rx.txt
myFile.close();
}
you need to do like this:
if (vw_get_message(buf, &buflen)) // If a message is received...
{
if (!myFile.open("rx.txt", O_RDWR | O_CREAT | O_AT_END)) // Try to open file for write
sd.errorHalt("opening rx.txt for write failed"); // If fails then error
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) // Try to begin communication with microSD
sd.initErrorHalt(); // If fails then error
for (int i = 0; i < buflen; i++) //For each received byte...
{
Serial.print((char)buf[i]);
myFile.println((char)buf[i]); //Write single byte to to myFile, rx.tx
}
myFile.close();
}
This is what I get when trying to compile the transmitter code:
In file included from sketch_oct18a.ino:4:
G:\Apps\Arduino\Sketches\libraries\SdFat/SdFat.h:294: error: conflicting return type specified for 'virtual void SdFile::write(uint8_t)'
G:\Apps\Arduino\hardware\arduino\cores\arduino/Print.h:48: error: overriding 'virtual size_t Print::write(uint8_t)'
sketch_oct18a:6: error: 'SdFat' does not name a type
sketch_oct18a.ino: In function 'void setup()':
sketch_oct18a:33: error: 'sd' was not declared in this scope
sketch_oct18a:33: error: 'SPI_HALF_SPEED' was not declared in this scope
sketch_oct18a:36: error: no matching function for call to 'SdFile::open(const char [9], int)'
G:\Apps\Arduino\Sketches\libraries\SdFat/SdFat.h:238: note: candidates are: uint8_t SdFile::open(SdFile&, uint16_t, uint8_t)
G:\Apps\Arduino\Sketches\libraries\SdFat/SdFat.h:239: note: uint8_t SdFile::open(SdFile&, char*, uint8_t)
G:\Apps\Arduino\Sketches\libraries\SdFat/SdFat.h:241: note: uint8_t SdFile::open(SdFile&, char*)
sketch_oct18a:37: error: 'sd' was not declared in this scope
sketch_oct18a:36: error: no matching function for call to 'SdFile::open(const char [9], int)'
this error message clearly telling you that Sdfat does not have any overloaded function whose 1st argument is of const char [9], type.
you can pass argument like uint8_t SdFile::open(SdFile&, uint16_t, uint8_t) or other related overloaded functions only.
Well, I got it figured out. De-installed Arduino, re-installed again and now the SDfat library works.
My older sketches will need an update as they relied on other FAT libaries but I'll manage.
Anyway, I'll try the transmitter and receiver code again later this afternoon, I expect it to work now.
After that, It's time to implement it into my current sketch.
Ok, the transmission is received but not stored correctly when trying the first sketch.
I've tried swapping the SDcards but that didn't help. I ran sdformat on both cards and tried the example ReadWriteSdfat, that worked well.
Now, This is my code:
//Attach receiver module facing outwards from pins 2 to 5 for no breadboard setup
#include <VirtualWire.h>
#include <SdFat.h>
//Virtual Wire initialisations
const int receive_pin = 4;
const int transmit_en_pin = 7;
const int Vpin = 2;
const int GND = 5;
//SdFat initialisations
SdFat sd;
SdFile myFile;
const int chipSelect = 10;
void setup()
{
delay(1000);
Serial.begin(9600); // Debugging only
Serial.println("setup");
// Initialise the IO and ISR
vw_set_rx_pin(receive_pin);
vw_set_ptt_pin(transmit_en_pin);
vw_set_ptt_inverted(true); // Required for DR3100
pinMode(Vpin, OUTPUT); // Sets up pins for use
pinMode(GND, OUTPUT);
digitalWrite(Vpin, HIGH); // Sets up pin voltage levels
digitalWrite(GND, LOW);
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) // Try to begin communication with microSD
sd.initErrorHalt(); // If fails then error
if (!myFile.open("rx.txt", O_RDWR | O_CREAT | O_AT_END)) // Try to open file for write
sd.errorHalt("22opening rx.txt for write failed"); // If fails then error
vw_setup(2000); // Bits per sec
vw_rx_start(); // Start the receiver PLL running
}
void loop()
{
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)) // If a message is received...
{
if (!myFile.open("rx.txt", O_RDWR | O_CREAT | O_AT_END)) // Try to open file for write
sd.errorHalt("opening rx.txt for write failed"); // If fails then error
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) // Try to begin communication with microSD
sd.initErrorHalt(); // If fails then error
for (int i = 0; i < buflen; i++) //For each received byte...
{
Serial.print((char)buf[i]);
myFile.println((char)buf[i]); //Write single byte to to myFile, rx.tx
}
myFile.close();
}
}
But now I get the error:
error: opening rx.txt for write failed
This is the last error message in the sketch and I can't find out why. Do I need to close the file in void setup already?