Go Down

Topic: SD card variable file name (Read 26942 times) previous topic - next topic

PaulS

Quote
It would be nice if someone could explain the term + '0'
The values 4 and '4' are not the same. However, the difference between the values from 0 to 9 and the characters '0' to '9' is consistent, for each value of n. So,
'n' - n = '0'.

Therefore, what the term + '0' is doing is converting the value n to the character 'n'. (0 -> '0', 3 -> '3', etc.)
The art of getting good answers lies in asking good questions.

Gdunge

#16
Jan 26, 2016, 12:37 am Last Edit: Jan 26, 2016, 12:56 am by Gdunge
It would be nice if someone could explain the term + '0'
Characters are stored as bytes in memory.
When told to add a character to a number, the C compiler actually adds the corresponding byte.
The code for translating between bytes and characters is called the ASCII code.
Now look at an ASCII table. Here's one:

http://www.ascii-code.com/

With this in mind, you can try an example. Look up the decimal value of the symbol '0', add 6 to it, and look up the resulting symbol in the ASCII table.

Does this help explain what's going on?

Note that this trick only works for positive single-digit numbers! Try adding 10 to '0' and see what you get.

More info:

https://www.arduino.cc/en/Reference/Char

godo

Thanks PaulS and Gdunge,
I suspected it was some casting procedure, but I didn't quite get it. Now it is clearer.
I tried it differently first, like
Code: [Select]
filename[4] = char (day/10);
but that did not work. Why is that not the same?
Cheers

PaulS

Quote
Why is that not the same?
Suppose day is 17. Dividing 17 by 10 results in 1. Casting 1 to a character is valid, but the result is not the character '1'. It is a non-printing character.

http://www.asciitable.com/
The art of getting good answers lies in asking good questions.

Gdunge

#19
Jan 27, 2016, 07:22 pm Last Edit: Jan 27, 2016, 07:28 pm by Gdunge
Your question makes it look like you don't quite get the idea of the ASCII code.

Here is some history that might help:

https://en.wikipedia.org/wiki/ASCII

And here's my quick explanation.

The American Standard Code for Information Interchange (ASCII) is an ordered list of symbols (letters, numbers, punctuation, and "control characters"). Each symbol is given a number, starting at 0 and going up to 127.

To print letters on screen or paper, computers use the ASCII code to tell the device what symbol to print. If your Arduino program wants to print an "A" on the screen, it needs to send the appropriate number to the Serial device - which, for the letter "A", is the number 65.

So if your program does this:

Code: [Select]
Serial.write(65);

then this comes out:
Code: [Select]
A

Just for fun, here is a program that plays around with various ways to use the ASCII code to print things to the screen:

Code: [Select]
// Some exercises with the ASCII code
// You can find an ASCII code table in lots of places. Here's one:
// https://www.arduino.cc/en/Reference/ASCIIchart
// Doug Weathers, 27 Jan 2016

void setup()
{
  Serial.begin(9600);

  // print the capital letters ("A" = 65, "Z" = 90)
  // Just send the numbers corresponding to the letters we want to print on the screen
  for (int i = 65; i <= 90; i++)
  {
    Serial.write(i);
  }

  // Send a line feed code (LF) to skip down to the next line for our next piece of output
  Serial.write(10);

  // Send "Hello World!", followed by a LF
  // I looked up each letter in the ASCII table and typed the corresponding numbers into the array
  byte bytes[13] = {72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 10};
  for (int i = 0; i < 13; i++)
  {
    Serial.write(bytes[i]);
  }

  // Do it a bit easier, where you don't need to keep track of how many characters are in your array
  // The C compiler counts the numbers you typed in and correctly defines the array for you
  char chars[] = {72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 0};
  // println checks for the end of the line, marked by a zero, and that's how it knows to stop printing
  // Also it automatically puts on the LF codes for you.
  Serial.println(chars);

  // Do it even easier
  // The C compiler looks up each letter in the ASCII table and puts the correct byte into the array,
  // then puts a zero at the end to mark the end of the string.
  char cstring[] = "Hello World!";
  Serial.println(cstring);

  // Do it the easiest way
  // This is called a string constant or string literal
  Serial.println("Goodbye, cruel world!");
}

void loop() {
  // put your main code here, to run repeatedly:

}


The output looks like this:
Code: [Select]
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Hello World!
Hello World!
Hello World!
Goodbye, cruel world!


For more clues, check out these sections of the Arduino reference:

https://www.arduino.cc/en/Reference/Char
https://www.arduino.cc/en/Serial/Write
https://www.arduino.cc/en/Serial/Print
https://www.arduino.cc/en/Serial/Println

NickPeak

I got it working - and can see where I was off and that I need to understand pointers better.  I know I probably shouldn't use "filename" inside-of and outside-of the function, but it compiles and the SD card functions accept it with no problems, so: <shrug>.

Thank you Paul.
Ex uno disce omnes
___
in setup:
char filename[] = "00000000.CSV";

function call:
getFilename(filename);

function:
  void getFilename(char *filename) {
    DateTime now = RTC.now(); int year = now.year(); int month = now.month(); int day = now.day();
    filename[0] = '2';
    filename[1] = '0';
    filename[2] = year%10 + '0';
    filename[3] = year%10 + '0';
    filename[4] = month/10 + '0';
    filename[5] = month%10 + '0';
    filename[6] = day/10 + '0';
    filename[7] = day%10 + '0';
    filename[8] = '.';
    filename[9] = 'C';
    filename[10] = 'S';
    filename[11] = 'V';
    return;
  }

Thanks to all involved for this example. I have an engineering project for school requiring a datalogger, and this has finally rescued me from months of frustration.  My files are now saving with a timestamp for a filename, so I create a new file each time rather than overwriting an existing one.  The design judges at my competition will love that functionality. I'm a bit overwhelmed of how simple the solution was, but I'm so glad it's working now.

Cheers,

-Nick

boyan88

#21
Nov 23, 2016, 08:56 pm Last Edit: Nov 26, 2016, 05:27 pm by boyan88
Hello,
I used a piece of code, but did not succeed, the date is arranged true but in the end there is always the symbol. I think it comes SD.open problem can not create or data written on it.


Code: [Select]
20161126.CSV &&



PaulS

Quote
I used a piece of code, but did not succeed
Too bad you didn't use the right code. If you need help making your "piece of code" into "the right code", you'll need to post your code.
The art of getting good answers lies in asking good questions.

bgerd

#23
Feb 09, 2017, 01:39 am Last Edit: Feb 09, 2017, 01:49 am by bgerd
Hi Godo,

The '0' is the ascii character of the number 0. As an int it is actually equal to 48 (i.e. 0x30).

In this case it acts as an offset. So that

Code: [Select]
(char) ('0'+0) = (char) (48+0) = (int) 49 =  '0'
(char) ('0'+1) = (char) (48+1) = (int) 50 =  '1'
(char) ('0'+2) = (char) (48+2) = (int) 51 =  '2'
...
(char) ('0'+9) = (char) (48+9) = (int) 57 =  '9'

barsznica

#24
Sep 29, 2017, 06:22 am Last Edit: Sep 29, 2017, 06:35 am by barsznica
This is how I did it (even though I prefer to avoid Strings):
Code: [Select]
#include <TimeLib.h>
#include <DS1307RTC.h>
#include <SD.h
tmElements_t tm;          // #define DS1307_CTRL_ID 0x68

#define    BAUDRATE 115200
int           chipSelect=5;                                             // Chip Select pin for SD card

void setup()
{
  Serial.begin(BAUDRATE);
  Serialprint("Init. SD card...");
  if (!SD.begin(chipSelect))
  { // see if the card is present and can be initialized:
    Serialprint("Card failed, or not present\n");
  }
  else Serialprint("Card initialized.\n");

  RTC.read(tm);
  date = ( (uint32_t)tm.Day + 100*(uint32_t)tm.Month + 10000*(uint32_t)tmYearToCalendar(tm.Year) );
  time = ( (uint32_t)tm.Second + 100*(uint32_t)tm.Minute + 10000*(uint32_t)tm.Hour );
 
  // Not sure if creates new file if it !exists.
  String logFile = String(date);
  logFile += String(".csv");
  File dataFile = SD.open(logFile, FILE_WRITE);
  if (dataFile)
  {
   Serialprint("-----------Logging data-----------\n");
   dataFile.print("Date: ");
   dataFile.print(date);
   dataFile.print("UTCTime: ");
   dataFile.print(time);
   dataFile.print('\n');
   dataFile.close();
   Serialprint("Data logged...\n");
  }
  else
  {
   Serialprint("Logging error!!!!!!!!!!!!!!!!\n");
  }

void loop()
{
  ;
  // Do what you want here
}

I have cut these bits out of other code, so I hope I haven't missed anything ;)
I'm using UTC time, so I don't have to worry 'bout Daylight Savings
Lights, music, electronics, Action!

Go Up