![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
tassoeb
Joined: 29 Oct 2015 Posts: 7
|
DataLogger using pic18f4550 |
Posted: Thu Nov 05, 2015 11:31 am |
|
|
Hello everyone,
I am starting to work with a pic18f4550 and I need to develop a datalogger to my project. For now, all the help I want is to to create a text file and save it to a SD Card.
I am trying to use the "fat.c" and the "mmcsd.c" standard library from ccs (eventhough I am not sure if that's the best way), my code does not give me any errors but when I check on my computer there is no file in the SD Card.
Code: | #include <18f4550.h>
#use delay(clock = 4000000)
#fuses HS, NOWDT, PUT, NOLVP
#use rs232(baud=9600, UART1, errors)
#define MMCSD_PIN_SCL PIN_B1 //o
#define MMCSD_PIN_SDI PIN_C7 //i
#define MMCSD_PIN_SDO PIN_B0 //o
#define MMCSD_PIN_SELECT PIN_B4 //o
#include <mmcsd.c>
#include <fat.c>
main()
{
char filename[]="test.txt";
fat_init();
mk_file(filename);
mmcsd_write_byte(0, filename);
} |
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Thu Nov 05, 2015 11:46 am |
|
|
Big big problem. How are you handling the conversion between 5v PIC, and 3.3v SD card?. Your PIC requires 4.2v minimum to run USB.
The SPI input on the PIC _requires_ the signal to go up to 0.8* the chip's supply voltage. So 4v. 3.3v SD card cannot do this without a buffer. Then the outputs on the PIC are 5v, and the SD card is only 3.3v. There needs to be a resistive divider at the minimum, or you will damage the card.
Honestly far easier to use a 45K50, and run everything at 3.3v.
If not, then go to the Brush electronics site:
<http://www.brushelectronics.com/index.php?page=projects>
Get the Ethernet reference design for the 4620, and look at the circuit used to interface the SD to the PIC. This works. Note also the resistive pull-ups. These are _required_ to make the SD card wake up in the correct mode.
As a separate comment, the SD drivers available from this site are more flexible than the CCS supplied examples, and work well.
For the CCS drivers, get the upgrades from the code forum. Some of these are necessary (depending on the size of your card - if >2GB, the SDHC modification is required).
Then once your hardware has a chance of working, realise that after having made the file, you need to open this, then write to the stream returned by the open (you don't just write to the file name), then close this. |
|
![](templates/subSilver/images/spacer.gif) |
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Thu Nov 05, 2015 1:38 pm |
|
|
Hi,
You know, if this is a one-off project, something like this is going to be much easier and faster!
https://www.sparkfun.com/products/9530 _________________ John
If it's worth doing, it's worth doing in real hardware! |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9174 Location: Greensville,Ontario
|
|
Posted: Thu Nov 05, 2015 8:10 pm |
|
|
ezflyer's option is a nice one and uses the SD devices.
I used the Vinculum solution as it was easier to use USB flashdrives for my clients as not all PCs have SD readers in them. Once the PIC datalogger code setup the data as a dotCSV file, the rest was easy. Having the data stored as CSV allowed instant importing into an eXcel spreadsheet.
yes the Vinculum parts were twice the price of the Sparkfun unit but it's 5 volts so NO logic level translation needed unlike the SD devices.
Jay |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Fri Nov 06, 2015 1:47 am |
|
|
as a further comment, the line in the original post: "my code does not give me any errors", is answered by the fact that the code _ignores_ the returns from the functions. For instance, 'fat_init', _returns_ an integer, which has the value 'EOF' if there was a problem, or 'GOODEC' if the call operated correctly (both #defined in the include file). Currently, the return is being ignored, so 'no wonder' it doesn't give any errors.... |
|
![](templates/subSilver/images/spacer.gif) |
tassoeb
Joined: 29 Oct 2015 Posts: 7
|
|
Posted: Fri Nov 06, 2015 8:14 am |
|
|
Ttelmah wrote: | Big big problem. How are you handling the conversion between 5v PIC, and 3.3v SD card?. Your PIC requires 4.2v minimum to run USB.
The SPI input on the PIC _requires_ the signal to go up to 0.8* the chip's supply voltage. So 4v. 3.3v SD card cannot do this without a buffer. Then the outputs on the PIC are 5v, and the SD card is only 3.3v. There needs to be a resistive divider at the minimum, or you will damage the card.
Honestly far easier to use a 45K50, and run everything at 3.3v.
If not, then go to the Brush electronics site:
<http://www.brushelectronics.com/index.php?page=projects>
Get the Ethernet reference design for the 4620, and look at the circuit used to interface the SD to the PIC. This works. Note also the resistive pull-ups. These are _required_ to make the SD card wake up in the correct mode.
As a separate comment, the SD drivers available from this site are more flexible than the CCS supplied examples, and work well.
For the CCS drivers, get the upgrades from the code forum. Some of these are necessary (depending on the size of your card - if >2GB, the SDHC modification is required).
Then once your hardware has a chance of working, realise that after having made the file, you need to open this, then write to the stream returned by the open (you don't just write to the file name), then close this. |
Thank you for you answer Ttelmah,
I am using an Adafruit MicroSD card breakout board, and I have already tested the functionality of the card and the board using another code (recording some bytes in it). So I am pretty much sure that the problem is not the hardware.
My biggest problem I think it is the software, I am not sure how both libraries "fat.c" and "mmcsd.c" should work together. Is the file being created correctly? Is it saving correctly?
Thanks again! |
|
![](templates/subSilver/images/spacer.gif) |
tassoeb
Joined: 29 Oct 2015 Posts: 7
|
|
Posted: Fri Nov 06, 2015 8:21 am |
|
|
temtronic wrote: | ezflyer's option is a nice one and uses the SD devices.
I used the Vinculum solution as it was easier to use USB flashdrives for my clients as not all PCs have SD readers in them. Once the PIC datalogger code setup the data as a dotCSV file, the rest was easy. Having the data stored as CSV allowed instant importing into an eXcel spreadsheet.
yes the Vinculum parts were twice the price of the Sparkfun unit but it's 5 volts so NO logic level translation needed unlike the SD devices.
Jay |
Hello temtronic,
For now I am trying just the basics saving a text file, but yes, my intention is to record a CSV file.
However my "mission" is to record directly to the SD card so after collect the data I can open in my computer.
Any suggestions about the code?
Thank you |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Fri Nov 06, 2015 8:40 am |
|
|
No it won't be being written to. You do not write to a file name. You open the file to get a 'handle', then write to the handle, then the file must be closed before the data will actually be committed (or you can 'flush' which forces the write). This is exactly the same as on a PC.... Look at the example. ex_fat.c, shows what has to happen.
Then you need to look at the status returned by calls.
Then you need the SDHC code modifications from the library. The SD drivers only support cards up to 2GB. Any card above this size will be SDHC (well actually there are a few old examples of 4GB cards that are not). |
|
![](templates/subSilver/images/spacer.gif) |
tassoeb
Joined: 29 Oct 2015 Posts: 7
|
|
Posted: Mon Nov 09, 2015 12:42 pm |
|
|
Hey guys,
I followed the ex_fat.c example and now I can get TXT file inside the SD card. My problem now, is that I can't append a text to the TXT file.
Any ideias?
Code: | #include <18f4550.h>
#use delay(clock = 4000000)
#fuses HS, NOWDT, PUT, NOLVP
#use rs232(baud=9600, UART1, errors)
#define MMCSD_PIN_SCL PIN_B1 //o
#define MMCSD_PIN_SDI PIN_C7 //i
#define MMCSD_PIN_SDO PIN_B0 //o
#define MMCSD_PIN_SELECT PIN_B4 //o
#include <mmcsd.c>
#include <fat.c>
#include <stdlib.h> // for atoi32
char endline[]="\r\n";
char a = "a";
int AppendFile(char *fileName, char *appendString)
{
FILE stream;
//printf("\r\nAppending '%s' to '%s': ", appendString, fileName);
if(fatopen(fileName, a, &stream) != GOODEC)
{
//printf("Error opening file");
return 1;
}
fatputs(appendString, &stream);
fatputs(endline, &stream);
if(fatclose(&stream) != GOODEC)
{
//printf("Error closing file");
return 1;
}
//printf("OK");
return 0;
}
main()
{
char filename[]="/test.txt";
char str[]="this is a test";
char str2[]="next line";
char *ptr;
fat_init();
format(2097152);
mk_file(filename);
ptr = str;
AppendFile(filename, ptr);
ptr=str;
AppendFile(filename, ptr);
mmcsd_write_byte(0, filename);
} |
|
|
![](templates/subSilver/images/spacer.gif) |
tassoeb
Joined: 29 Oct 2015 Posts: 7
|
unable to use FATOPEN |
Posted: Tue Nov 10, 2015 10:36 am |
|
|
Hello guys,
After doing some debugging I finally can create a file inside the SD Card but now I am having trouble to write (APPEND) in my test.txt file because it seems my fatopen function return me bad.
Can anybody help me?
Code: | #include <18f4550.h>
#use delay(clock = 4000000)
#fuses HS, NOWDT, PUT, NOLVP
#use rs232(baud=9600, UART1, errors)
#define MMCSD_PIN_SCL PIN_B1 //o
#define MMCSD_PIN_SDI PIN_C7 //i
#define MMCSD_PIN_SDO PIN_B0 //o
#define MMCSD_PIN_SELECT PIN_B4 //o
#include <mmcsd.c>
#include <fat.c>
#include <stdlib.h> // for atoi32
char endline[]="\r\n";
char a = "a";
int AppendFile(char *fileName, char *appendString)
{
FILE stream;
//printf("\r\nAppending '%s' to '%s': ", appendString, fileName);
if(fatopen(fileName, a, &stream) != GOODEC)
{
//printf("Error opening file");
return 1;
}
fatputs(appendString, &stream);
fatputs(endline, &stream);
if(fatclose(&stream) != GOODEC)
{
//printf("Error closing file");
return 1;
}
//printf("OK");
return 0;
}
main()
{
char filename[]="/test.txt";
char str[]="this is a test";
char str2[]="next line";
char *ptr;
fat_init();
format(2097152);
mk_file(filename);
ptr = str;
AppendFile(filename, ptr);
ptr=str;
AppendFile(filename, ptr);
mmcsd_write_byte(0, filename);
} |
Thank you! |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Nov 10, 2015 11:22 am |
|
|
Quote: | char a = "a";
if(fatopen(fileName, a, &stream) != GOODEC)
{
//printf("Error opening file");
return 1;
} |
What's string ? How is it stored ? What bytes are created by "a" ?
How much room do they take ?
Make a very small test program to study these issues. Look at the .LST
file to see what the compiler is doing. |
|
![](templates/subSilver/images/spacer.gif) |
tassoeb
Joined: 29 Oct 2015 Posts: 7
|
|
Posted: Tue Nov 10, 2015 11:42 am |
|
|
PCM programmer wrote: | Quote: | char a = "a";
if(fatopen(fileName, a, &stream) != GOODEC)
{
//printf("Error opening file");
return 1;
} |
What's string ? How is it stored ? What bytes are created by "a" ?
How much room do they take ?
Make a very small test program to study these issues. Look at the .LST
file to see what the compiler is doing. |
The A stands for APPEND (cause my compiler couldn't handle just "a") as it says in the fat.c library...
No need to bother anymore! Problem solved, it is working!
I figured out how to create the file and edit it
Thank you all! |
|
![](templates/subSilver/images/spacer.gif) |
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Tue Nov 10, 2015 1:02 pm |
|
|
Hi,
You benefited from the collective wisdom of the forum, so please post your working solution so that others coming after you may benefit from this work! _________________ John
If it's worth doing, it's worth doing in real hardware! |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Nov 10, 2015 6:16 pm |
|
|
He's left the thread. For others who wondered what I was talking about,
here is the correct way to call fatopen():
In the method below, the file mode (the middle parameter) is passed
as a string directly in the parameter list:
Code: | if(fatopen(fileName, "a", &stream) != GOODEC)
{
}
|
Here's another way to do it, with a mode array declaration.
Code: |
char mode[] = "a";
if(fatopen(fname, mode, stream) != GOODEC)
{
} |
Here is a test program to show his method (which does not work),
compared to the correct method of passing the string "a" to the
fatopen() function:
Code: |
#include <18F4620.h>
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
char a = "a";
char filemode[] = "a";
void myfunc(char mode[])
{
printf("%x \n\r", mode[0]);
}
//============================
void main()
{
myfunc(a);
myfunc(filemode);
while(TRUE);
} |
Here is the output of the program when run in MPLAB v8.92 simulator:
His method passes 0x00 to the fileopen() function, and it will not work.
The correct method passes 0x61 which is lower-case ASCII 'a', and that's
what fileopen() wants to see.
Also, when you compile the file, his method gives a String Truncated
warning for this line:
That should have given him a clue that something was wrong:
Quote: | Executing: "C:\Program files\Picc\CCSC.exe" +FH "PCH_Test.c" +DF +LY -T -A +M -Z +Y=9 +EA #__18F4620=TRUE
>>> Warning 230 "PCH_Test.c" Line 7(1,1): String truncated Memory usage: ROM=0% RAM=0% - 0%
0 Errors, 1 Warnings.
Build Successful. |
|
|
![](templates/subSilver/images/spacer.gif) |
mparzgnat
Joined: 22 Mar 2016 Posts: 2
|
Questions on char * not char. |
Posted: Tue Mar 22, 2016 7:13 am |
|
|
I got the same truncation warning, but I was using a character pointer. I posted a stripped down version of the function, normally it reads ID from I2C device, and on top the truncation warning it also returns a garbage pointer in Rtrn.
char *HDC1xxxId(int16 *RtrnDeviceId)
{
char *Rtrn = NULL;
volatile union_sixteen temp_device_id;
temp_device_id.b[1] = 0x10; //Read high byte first
temp_device_id.b[0] = 0x00; //Then Low byte
/**Convert to string.**/
if (temp_device_id.full == 0x1050)
Rtrn = "HDC1080";
else
Rtrn = "Unrecognized Sensor";
/**Return device ID, if requested.**/
if (RtrnDeviceId)
*RtrnDeviceId = temp_device_id.full;
return(Rtrn);
}
Looking through documentation it seemed that "rom" might do the trick, but I got same results.
rom char *HDC1xxxId(int16 *RtrnDeviceId)
{
rom char *Rtrn = NULL;
volatile union_sixteen temp_device_id;
temp_device_id.b[1] = 0x10; //Read high byte first
temp_device_id.b[0] = 0x00; //Then Low byte
/**Convert to string.**/
if (temp_device_id.full == 0x1050)
Rtrn = "HDC1080";
else
Rtrn = "Unrecognized Sensor";
/**Return device ID, if requested.**/
if (RtrnDeviceId)
*RtrnDeviceId = temp_device_id.full;
return(Rtrn);
}
It seems fairly trivial function with fairly simple 'C' constructs. I am using a PIC18F26k22, what am I doing wrong? |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|