How do I program a PIC to save sensor data to a CSV file?

Thread Starter

Maricelle

Joined Jan 21, 2021
7
I don't know if this has been asked before, but I'm doing a project where I need to sense temperatures and humidities of an enclosure, using a PIC32 microcontroller. Is there a way to save the data from the sensors to a CSV file?
Thanks in advance!
 

Papabravo

Joined Feb 24, 2006
16,118
Sure. You send the data from the PIC to a serial port as lines of comma separated text, with CRLF at the end of each line.
You receive the data with a terminal emulator program and save the data to a file.
No programming required outside of the PIC
 

ericgibbs

Joined Jan 29, 2010
12,902
hi Maricelle,
Welcome to AAC.
The method I use is to store the data as ASCII text, with a 'comma' suffix.
Do you have more details of the program you could post.?
E
 

andrewmm

Joined Feb 25, 2011
1,467
I don't know if this has been asked before, but I'm doing a project where I need to sense temperatures and humidities of an enclosure, using a PIC32 microcontroller. Is there a way to save the data from the sensors to a CSV file?
Thanks in advance!
@Maricelle

May be you could let us know your level of expertise with the PIC32 and the tool chain, and we can tailor orur answers better to your needs.

Is this home work / project work ?
 

Thread Starter

Maricelle

Joined Jan 21, 2021
7
@Maricelle

May be you could let us know your level of expertise with the PIC32 and the tool chain, and we can tailor orur answers better to your needs.

Is this home work / project work ?
Hi, Andrew.
Thanks for this - I'm a final year Mechanical Engineering student with very little experience with PICs and this is for a personal project.
 

Thread Starter

Maricelle

Joined Jan 21, 2021
7
This is what I have in terms of my programming for it - I got hold of a template for ADC code and tried to modify it, since all of my sensors are digital. Please feel free to critique it, since I'm still teaching myself how to programme it and I'm not too sure if what I've left in is at all appropriate.

C:
int main(int argc, char** argv) {
    //Unlock sequence for SPLLCON and OSCCON registers.
    SYSKEY = 0; // force lock
    SYSKEY = 0xAA996655; // unlock sequence
    SYSKEY = 0x556699AA; // lock sequence

    //Temporarily switch to 8MHz FRC (without PLL), so we can safely change the PLL settings,
    //in case we had previously been already running from the PLL.
    OSCCON = OSCCON & 0xF8FFF87E; //FRC configured for 8MHz output, and set NOSC to run from FRC with divider but without PLL.
    if (OSCCONbits.COSC != OSCCONbits.NOSC) {
        //Initiate clock switching operation.
        OSCCONbits.OSWEN = 1;
        while (OSCCONbits.OSWEN == 1); //Wait for switching complete.
    }

    //Configure the PLL to run from the FRC, and output 24MHz for the CPU + Peripheral Bus (and 48MHz for the USB module)
    SPLLCON = 0x02050080; //PLLODIV = /4, PLLMULT = 12x, PLL source = FRC, so: 8MHz FRC * 12x / 4 = 24MHz CPU and peripheral bus frequency.

    //Now switch to the PLL source.
    OSCCON = OSCCON | 0x00000101; //NOSC = SPLL, initiate clock switch (OSWEN = 1)


    //Wait for PLL startup/lock and clock switching operation to complete.
    for (i = 0; i < 100000; i++) {
        if ((CLKSTATbits.SPLLRDY == 1) && (OSCCONbits.OSWEN == 0))
            break;
    }


    //Enable USB active clock tuning for the FRC
    OSCTUN = 0x00009000; //active clock tuning enabled, source = USB
    SYSKEY = 0; //Re-lock oscillator registers 


    ANSELA = 0;
    ANSELB = 0;
    ANSELC = 0;
    ANSELD = 0; //set all as digital
    
    TRISCbits.TRISC13 = 0;

    //##############################################################
    __builtin_disable_interrupts();


    // Set RB2/AN4 as an digital input
    ANSELBbits.ANSB2 = 0;
    TRISBbits.TRISB2 = 1;
    
    // Set RC8/AN14 as an digital input
    ANSELCbits.ANSC8 = 0;
    TRISCbits.TRISC8 = 1;


    // Add 3 inputs above to the scan list
    AD1CSS = (1 << 4) | (1 << 14);

    AD1CON2bits.CSCNA = 1; // Enable scan
    AD1CON5bits.ASEN = 1; //auto scan mode
    // Set number conversion per interrupt to the number of inputs (3)
    AD1CON2bits.SMPI = 2 - 1;
    AD1CON2bits.BUFM = 0;
    // Clock from peripheral clock TPB
    AD1CON3bits.ADRC = 0;
    AD1CHSbits.CH0NA = 0b000; // Negative input is VrefL = AVSS
    AD1CON2bits.VCFG = 0b000; //AVdd AVss
    

    TRISCbits.TRISC8 = 0;         // set RC8=OCM3E capture
    CCP3CON1 = 0;        // initialise all values as 0
    CCP3CON2 = 0;        // initialise all values as 0
    CCP3CON3 = 0;        // initialise all values as 0
    CCP3CON1bits.CCSEL = 0;     // PWM mode
    CCP3CON1bits.CLKSEL = 0;     //clock source = system clock
    CCP3CON1bits.MOD = 0b0100;     //Dual Edge Compare mode State when go HIGH and LOW
    CCP3CON2bits.OCEEN = 1;     //enable OCM3E/RC15 (blue)
    CCP3RA = 0;        //Value to go HIGH
    CCP3RB = 40950;        //Value to go LOW
    CCP3PR = 40950;        //Value to overflow, start from 0
    CCP3CON1bits.ON = 1;          //enable module

    
    while (1) {
        Nop();      //do nothing
    }
}
 

nsaspook

Joined Aug 27, 2009
8,382
This is what I have in terms of my programming for it - I got hold of a template for ADC code and tried to modify it, since all of my sensors are digital. Please feel free to critique it, since I'm still teaching myself how to programme it and I'm not too sure if what I've left in is at all appropriate.

C:
int main(int argc, char** argv) {
    //Unlock sequence for SPLLCON and OSCCON registers.
    SYSKEY = 0; // force lock
    SYSKEY = 0xAA996655; // unlock sequence
    SYSKEY = 0x556699AA; // lock sequence

    //Temporarily switch to 8MHz FRC (without PLL), so we can safely change the PLL settings,
    //in case we had previously been already running from the PLL.
    OSCCON = OSCCON & 0xF8FFF87E; //FRC configured for 8MHz output, and set NOSC to run from FRC with divider but without PLL.
    if (OSCCONbits.COSC != OSCCONbits.NOSC) {
        //Initiate clock switching operation.
        OSCCONbits.OSWEN = 1;
        while (OSCCONbits.OSWEN == 1); //Wait for switching complete.
    }

    //Configure the PLL to run from the FRC, and output 24MHz for the CPU + Peripheral Bus (and 48MHz for the USB module)
    SPLLCON = 0x02050080; //PLLODIV = /4, PLLMULT = 12x, PLL source = FRC, so: 8MHz FRC * 12x / 4 = 24MHz CPU and peripheral bus frequency.

    //Now switch to the PLL source.
    OSCCON = OSCCON | 0x00000101; //NOSC = SPLL, initiate clock switch (OSWEN = 1)


    //Wait for PLL startup/lock and clock switching operation to complete.
    for (i = 0; i < 100000; i++) {
        if ((CLKSTATbits.SPLLRDY == 1) && (OSCCONbits.OSWEN == 0))
            break;
    }


    //Enable USB active clock tuning for the FRC
    OSCTUN = 0x00009000; //active clock tuning enabled, source = USB
    SYSKEY = 0; //Re-lock oscillator registers


    ANSELA = 0;
    ANSELB = 0;
    ANSELC = 0;
    ANSELD = 0; //set all as digital
   
    TRISCbits.TRISC13 = 0;

    //##############################################################
    __builtin_disable_interrupts();


    // Set RB2/AN4 as an digital input
    ANSELBbits.ANSB2 = 0;
    TRISBbits.TRISB2 = 1;
   
    // Set RC8/AN14 as an digital input
    ANSELCbits.ANSC8 = 0;
    TRISCbits.TRISC8 = 1;


    // Add 3 inputs above to the scan list
    AD1CSS = (1 << 4) | (1 << 14);

    AD1CON2bits.CSCNA = 1; // Enable scan
    AD1CON5bits.ASEN = 1; //auto scan mode
    // Set number conversion per interrupt to the number of inputs (3)
    AD1CON2bits.SMPI = 2 - 1;
    AD1CON2bits.BUFM = 0;
    // Clock from peripheral clock TPB
    AD1CON3bits.ADRC = 0;
    AD1CHSbits.CH0NA = 0b000; // Negative input is VrefL = AVSS
    AD1CON2bits.VCFG = 0b000; //AVdd AVss
   

    TRISCbits.TRISC8 = 0;         // set RC8=OCM3E capture
    CCP3CON1 = 0;        // initialise all values as 0
    CCP3CON2 = 0;        // initialise all values as 0
    CCP3CON3 = 0;        // initialise all values as 0
    CCP3CON1bits.CCSEL = 0;     // PWM mode
    CCP3CON1bits.CLKSEL = 0;     //clock source = system clock
    CCP3CON1bits.MOD = 0b0100;     //Dual Edge Compare mode State when go HIGH and LOW
    CCP3CON2bits.OCEEN = 1;     //enable OCM3E/RC15 (blue)
    CCP3RA = 0;        //Value to go HIGH
    CCP3RB = 40950;        //Value to go LOW
    CCP3PR = 40950;        //Value to overflow, start from 0
    CCP3CON1bits.ON = 1;          //enable module

   
    while (1) {
        Nop();      //do nothing
    }
}
This type of copy/paste with little knowledge of what's happening won't help you with understanding the hardware.
What PIC32 chip are you using? What programming environment and tool set are you using?
 

Thread Starter

Maricelle

Joined Jan 21, 2021
7
This type of copy/paste with little knowledge of what's happening won't help you with understanding the hardware.
What PIC32 chip are you using? What programming environment and tool set are you using?
I must agree with you about that, since it really hasn't helped as much as I hoped it would. :/
I'm using a PIC32MM0256GPM064 in a Microchip development board with MPLABX.
 

nsaspook

Joined Aug 27, 2009
8,382
That makes things clear about what hardware needs to be configured and what pin options can be used during programming. It have a usb What exactly do you want to connect to the board for data collection? What interfaces need to be configured and assigned to pins for proper hardware connection. A quick look shows the Microchip demo software is outdated and uses the old C32 compiler while modern code should use XC32 with the MCC for framework code generation.

https://microchipdeveloper.com/32bit:pic-mm
 
Last edited:

s14rs4

Joined Sep 15, 2016
69
Binary, I think - am I correct that I can convert it to decimals using the sprintf() function?
I am not familiar with PIC's so I can't help you there, I have only used Arduinos. But if if you convert your data into a text string, you can use PLX-DAQ to insert your data directly into an Excel spreadsheet in real time, from there you can export it to a csv file. It is free software and has instructions in how to format the data.
 
Top