Go Down

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

#### PaulS

#15
##### Jan 20, 2016, 05:14 pm
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.)

#### Gdunge

#16
##### Jan 26, 2016, 12:37 amLast 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.

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

#### godo

#17
##### Jan 26, 2016, 03:10 pm
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

#18
##### Jan 26, 2016, 08:19 pm
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/

#### Gdunge

#19
##### Jan 27, 2016, 07:22 pmLast 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 2016void 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]
`ABCDEFGHIJKLMNOPQRSTUVWXYZHello 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

#20
##### Feb 11, 2016, 12:31 am
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 pmLast 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

#22
##### Nov 28, 2016, 01:10 pm
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.

#### bgerd

#23
##### Feb 09, 2017, 01:39 amLast 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 amLast 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.htmElements_t tm;          // #define DS1307_CTRL_ID 0x68 #define    BAUDRATE 115200 int           chipSelect=5;                                             // Chip Select pin for SD cardvoid 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!

#### noname2327

#25
##### Dec 21, 2017, 01:31 pm
___
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;
}

Hello,

How Can i use this code with DS1302? Can someone help me rewrite this code?

Thanks,
Peter

#### PaulS

#26
##### Dec 21, 2017, 02:52 pm
Quote
How Can i use this code with DS1302?
That code creates a file name that is based on the date and time. It does not care how the date and time are obtained. Surely, you have some code which can get the date and time from the DS1302.

Go Up