Using C, C++ functions in Arduino IDE

Hello,
By way of introduction I am a professional electronics technician. (for many years) I am not a programmer. I do understand the very basics of programming.

My question is:
Is it possible to use C and/or C++ standard functions directly within an Arduino sketch? (MEGA2560 R3 with an Adafruit Data Logger shield)
In particular I’m interested in using “fscanf()”. I have “include <stdio.h>” and “include <SD.h>” in my sketch. It won’t work. Sketch “dumpfile.ino” does work and will dump the file to the serial monitor.
If it is possible, could you please give me a basic example of reading from the Data Logger shield?
I want to read a .csv file of floats, one float at a time for further math massaging.
If not, then not.

Thank you.
oldfox

Where is your code?

fscanf works but you have to use the correct parameters. fscanf() expects a pointer to a FILE object, while SD.open() returns a File object (C is case sensitive!).

Hey OldFox, you might want to bookmark this page: http://www.nongnu.org/avr-libc/user-manual/modules.html

And from the stdio.h page:

int fscanf ( FILE * __stream, const char * __fmt, ... )

The function fscanf performs formatted input, reading the input data from stream.

I did write a lot of code years ago and never liked fscanf() since my own I/O routines gave me much better error handling. Before I learned C (late 80's) I was already doing character-based I/O, even had a search that walked through the match list in between user keystrokes. I can tell ya that character-based input has an even bigger advantage on these RAM-challenged microcontrollers! Even at 115,200 baud there's time to do a lot between serial data arriving, even if it's just blinking lights or reading sensors.

GoForSmoke… thanks.
I have let a little bit of smoke out of parts in my lifetime. The code you show still has that ‘case sensitive’ issue. See "pylon’s’ post above.

You cannot use fscanf() for the objects returned by SD.open(). You have to use the utilities that the Arduino Stream class offers you.

You still haven't posted your code so we cannot help you further.

1oldfox:

GoForSmoke... thanks. I have let a little bit of smoke out of parts in my lifetime. The code you show still has that 'case sensitive' issue. See "pylon's' post above.

My code? That's from the doc for the GNU C++ stdio library! GNU C++ is what the Arduino IDE uses!

I don't use fscanf(), have not since I first checked it out 25 years ago. All I can say is watch the return for errors.

Here is the pertinent part of my code. The rest is way too long to post.

#include <SD.h>
#include <stdio.h>
 
int coordIndex = 0; // this is going to be an index into coordList
//  coordList[] should be built from a stream from the SD card, not typed in --- that's my issue
float coordList[100] = {0.10,0.20,0.30,0.40,0.50,0.60,0.70,0.80,0.90,1.00,1.10,1.20,1.30,1.40};
float coord; //where we're going to store the next float we read

const int chipSelect = 10;
void setup()
{
  Serial.begin(9600);
  pinMode(SS, OUTPUT);
 
  Serial.print("Initializing SD card...");
  if (!SD.begin(chipSelect))
  {
    Serial.println("Card failed, or not present");
    return;
  }
  Serial.println("card initialized.");

  File dataFile = SD.open("MEGA.csv");  // <--- C++ / Arduino "case sensitive" issue

  if (dataFile)                                  
  {                                              
  while (dataFile.available())                   
  //  if (fscanf(dataFile,"%f",&coord) == 1)  
      {                                          
  //    coordList[coordIndex++] = coord;         
      Serial.write(dataFile.read());             
  //    Serial.println(coord);                   
      }                                          
  dataFile.close();                              
  }                                              
  else                                           
  {                                              
    Serial.println("error opening MEGA.csv");    
  }                                              
}

void loop()
  {
// the rest of my sketch goes here
  }

The sketch runs properly as above. Using comments to cycle in the fscanf won’t work and the Arduino code, “while (dataFile.available())” and “Serial.write(dataFile.read());” does work.

if (fscanf(dataFile,"%f",&coord) == 1)

The "%f" doesn't work in the AVR version of the libc anyway, so you have to use strtof() for this which also means you have to read in the necessary characters yourself. What delimiter character are you using in your file?

And edit your post and insert code tags!

pylon Thanks. I am using "comma" for my delimiter. I'll give strtof() a try. Please excuse me for not being within forum protocol. I rarely post anything on forums. I will use the "code tag" from now on. Thanks for the heads up.

So use the readBytesUntil() method of the Stream class to read the next string representation of your float into a buffer:

  size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character
  // terminates if length characters have been read, timeout, or if the terminator character  detected
  // returns the number of characters placed in the buffer (0 means no valid data found)

after that you can use strtof() to convert that buffer into a float.

thanks again pylon.

I forgot to mention, there is stdio.h but on Arduino no default stdin or stdout as used on PC's.

GoForSmoke... Yeah, I'm beginning to discover those things about Arduino. Maybe someday the Arduino IDE (compiler) will be able to handle standard C and/or C++ functions Thanks, oldfox

"If it ain't broke, fix it 'til it is"

It is possible to configure the stdin, stdout, stderr streams to access the Serial device (or any other mechanism you fancy) if you want - you just need to write the put/get functions and associated them with the streams using fdevopen().

Maybe someday the Arduino IDE (compiler) will be able to handle standard C and/or C++ functions

It already is but you're using a library which does not use the same structures and data types as the standard C functions support. Keep in mind that the Arduino is an embedded platform with a small microcontroller which has 2kB of RAM. Don't expect exactly the same functionality as you have with todays PCs which have gigabytes of RAM.

MEGA2560 has 8k expandable to direct-address 64k and there's a bank-switched 512k shield....

And then there's the Due which is a 48 MHz 32-bit ARM with lots of RAM, a world apart from an UNO.

Some of us were running C on PC-XT's with 256k or less. I'm sure that some ran C on Z-80's, 8080's and 64k RAM or less but I was running BASIC and FORTH in those days.

The Arduino IDE is tailored to make AVR programming easier. The whole setup() and loop() concept is square one into real time coding where main() is square zero.

MEGA2560 has 8k expandable to direct-address 64k and there's a bank-switched 512k shield....

And then there's the Due which is a 48 MHz 32-bit ARM with lots of RAM, a world apart from an UNO.

Does that mean you think the AVR-libc should support "%f" in it's print and scan functions just because there is an 8k version of an ATmega controller?

The Due is another league and therefore has a separate forum. IDE support for it is in beta.

pylon: Does that mean you think the AVR-libc should support "%f" in it's print and scan functions just because there is an 8k version of an ATmega controller?

It does. In fact, it provides three different versions *each*of printf and scanf that can do different conversions depending on what you're using in your program to cut down on memory. The two problems here are that 1) printf sucks and is monolithic, making it impossible for the linker to know what version you want to use without you telling it and 2) the arduino IDE tells it to use the version that can do everything except floating point support and 3) the arduino IDE does not let you change build parameters without a recompile.

If you move away from the IDE you can use printf by just adding -Wl,-u,vfprintf -lprintf_flt -lm to the compiler line. Also, I believe IDE 1.5 lets you change the parameters passed to gcc. http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#gaa3b98c0d17b35642c0f3e4649092b9f1

pylon:

MEGA2560 has 8k expandable to direct-address 64k and there's a bank-switched 512k shield....

And then there's the Due which is a 48 MHz 32-bit ARM with lots of RAM, a world apart from an UNO.

Does that mean you think the AVR-libc should support "%f" in it's print and scan functions just because there is an 8k version of an ATmega controller?

Not really, just pointing out that "Arduino" is not limited to 2k RAM.

As I wrote before, I quit using fscan() as soon as I learned it. I want my users to get error feedback the moment they hit a key that doesn't fit the input format. It doesn't require users to re-enter complete text.