Go Down

Topic: Datalogging using MCP3208 (Read 699 times) previous topic - next topic

haziqamjad

Hi
I am using MCP3208 as an external adc and writing its data onto sd card. On the first iteration of loop , i get the right voltage values but afterwards i am getting wrong values.


Here is my code and circuit diagram

Any kind of help would be appreciated

jremington

#1
Jun 22, 2018, 09:33 pm Last Edit: Jun 22, 2018, 09:35 pm by jremington
Use of Strings with Arduino causes memory errors and eventually, program crashes. Get rid of them.

To test whether that String-induced errors are responsible for the current problem, write a simple program that just monitors the ADC and prints the result on the serial monitor, without using String objects.

OP's code, posted properly:

Code: [Select]
#include <Wire.h>
#include <RTClib.h>
#include <SPI.h>
#include <SD.h>

RTC_DS1307 RTC;




#define SELPIN 10 //Selection Pin
#define DATAOUT 11//MOSI
#define DATAIN  12//MISO
#define SPICLOCK  13//Clock
#define aref_voltage 5
#define chipSelect  9//CS for Sd card is PB1 or PIN 9

//const int chipSelect = 9;   //DIGITAL PIN 9(PB1) AS CHIP SELECT OF SD CARD
float readvalue,voltage0,voltage1,voltage2,voltage3,voltage4,voltage5;

void setup(){
 //set pin modes
 pinMode(SELPIN, OUTPUT);
pinMode(chipSelect, OUTPUT);
 pinMode(DATAOUT, OUTPUT);
 pinMode(DATAIN, INPUT);
 pinMode(SPICLOCK, OUTPUT);

 //pinMode(8,OUTPUT);
 //disable device to start with
 
 digitalWrite(SELPIN,HIGH);
 digitalWrite(DATAOUT,LOW);
 digitalWrite(SPICLOCK,LOW);
 


 Serial.begin(9600);
 Wire.begin();
RTC.begin();

// following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));
/*
  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect))
  {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");
  */
}


float read_adc(int channel){
  int adcvalue = 0;
  byte commandbits = B11000000; //command bits - start, mode, chn (3), dont care (3)

  //allow channel selection
  commandbits|=((channel-1)<<3);

  digitalWrite(SELPIN,LOW); //Select adc
  // setup bits to be written
  for (int i=7; i>=3; i--){
    digitalWrite(DATAOUT,commandbits&1<<i);
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);   
  }

  digitalWrite(SPICLOCK,HIGH);    //ignores 2 null bits
  digitalWrite(SPICLOCK,LOW);
  digitalWrite(SPICLOCK,HIGH); 
  digitalWrite(SPICLOCK,LOW);

  //read bits from adc
  for (int i=11; i>=0; i--){
    adcvalue+=digitalRead(DATAIN)<<i;
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);
  }
  digitalWrite(SELPIN, HIGH); //turn off device
  return adcvalue;
}

void(*resetFunc)(void)=0;

void loop() {
 


DateTime now = RTC.now();
int day = now.day();
int month = now.month();
int year = now.year();
int hour = now.hour();
int minute = now.minute();
int second = now.second();
 String slash = "/";
 String colon = ":";
 String date = day + slash + month + slash + year;
 String Time = hour + colon + minute + colon + second;
 Serial.println(date);
 Serial.println(Time);
 
   readvalue = read_adc(0);
   voltage0 = (aref_voltage*readvalue)/4096;
// Serial.println(voltage0);
  readvalue = read_adc(1);
voltage1 = (aref_voltage*readvalue)/4096;
// Serial.println(voltage1);
 readvalue = read_adc(2);
voltage2 = (aref_voltage*readvalue)/4096;
// Serial.println(voltage2);
 readvalue = read_adc(3);
voltage3 = (aref_voltage*readvalue)/4096;
// Serial.println(voltage3);
 readvalue = read_adc(4);
voltage4 = (aref_voltage*readvalue)/4096;
 //Serial.println(voltage4);
 readvalue = read_adc(5);
voltage5 = (aref_voltage*readvalue)/4096;
//Serial.println(voltage5);
// Serial.println(" ");

 String dataString ="";
 dataString += String(voltage0);
  dataString += ",";
 dataString += String(voltage1);
  dataString += ",";
 dataString += String(voltage2);
  dataString += ",";
 dataString += String(voltage3);
 dataString += ",";
 dataString += String(voltage4);
  dataString += ",";
 dataString += String(voltage5);
  dataString += ",";
  Serial.println(dataString);
 

 SD.begin(chipSelect);
   File dataFile = SD.open("FDR.csv", FILE_WRITE);
   
     // if the file is available, write to it:
  if (dataFile)
  {

    dataFile.println(Time);
   
    dataFile.println(date);

    dataFile.println(dataString);
   
   dataFile.close();
   
 
  }
 
 digitalWrite(chipSelect,LOW);
 delay(250);
 
}

haziqamjad

i have tried that....when i disable sd card operation, adc gives correct output values but i have to perform datalogging essentially

jremington

You do not have to use Strings for data logging. You NEVER have to use Strings for anything else, either.

haziqamjad

Also removed the strings and only monitored the data serially.......still the same problem

jremington

#5
Jun 22, 2018, 11:52 pm Last Edit: Jun 22, 2018, 11:52 pm by jremington
Post your code, with code tags, and describe the problem as clearly as you can.

Wawa

What device is connected to pin 0 and 1, or is that just a representation of the USB serial monitor.
What is VREF connected to.
What battery voltage, and is it connected to something low impedance.
Leo..

haziqamjad

Here is the code
Code: [Select]

//This code performs datalogging of an external adc on sd card
//MCP3208 is used for reading 6 analog channels
//This data is then appended in string named dataString
//dataString alongwith time and date are logged in a csv file

#include <Wire.h>
#include <RTClib.h>
#include <SPI.h>
#include <SD.h>

RTC_DS1307 RTC;




#define SELPIN 10 //Selection Pin
#define DATAOUT 11//MOSI
#define DATAIN  12//MISO
#define SPICLOCK  13//Clock
#define aref_voltage 5
#define chipSelect  9//CS for Sd card is PB1 or PIN 9


float readvalue,voltage0,voltage1,voltage2,voltage3,voltage4,voltage5;

void setup(){
 //set pin modes
 pinMode(SELPIN, OUTPUT);
pinMode(chipSelect, OUTPUT);
 pinMode(DATAOUT, OUTPUT);
 pinMode(DATAIN, INPUT);
 pinMode(SPICLOCK, OUTPUT);


 //disable device to start with
 
 digitalWrite(SELPIN,HIGH);
 digitalWrite(DATAOUT,LOW);
 digitalWrite(SPICLOCK,LOW);
 


 Serial.begin(9600);
 Wire.begin();
RTC.begin();

// following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));

}


float read_adc(int channel){
  int adcvalue = 0;
  byte commandbits = B11000000; //command bits - start, mode, chn (3), dont care (3)

  //allow channel selection
  commandbits|=((channel-1)<<3);
  digitalWrite(chipSelect,LOW);
  digitalWrite(SELPIN,LOW); //Select adc
  // setup bits to be written
  for (int i=7; i>=3; i--){
    digitalWrite(DATAOUT,commandbits&1<<i);
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);   
  }

  digitalWrite(SPICLOCK,HIGH);    //ignores 2 null bits
  digitalWrite(SPICLOCK,LOW);
  digitalWrite(SPICLOCK,HIGH); 
  digitalWrite(SPICLOCK,LOW);

  //read bits from adc
  for (int i=11; i>=0; i--){
    adcvalue+=digitalRead(DATAIN)<<i;
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);
  }
  digitalWrite(SELPIN, HIGH); //turn off device
  return adcvalue;
}



void loop() {
 


DateTime now = RTC.now();
int day = now.day();
int month = now.month();
int year = now.year();
int hour = now.hour();
int minute = now.minute();
int second = now.second();
 String slash = "/";
 String colon = ":";
 String date = day + slash + month + slash + year;
 String Time = hour + colon + minute + colon + second;
 Serial.println(date);
 Serial.println(Time);


  //reading adc
   readvalue = read_adc(0);
   voltage0 = (aref_voltage*readvalue)/4096;
Serial.println(voltage0);
  readvalue = read_adc(1);
voltage1 = (aref_voltage*readvalue)/4096;
 Serial.println(voltage1);
 readvalue = read_adc(2);
voltage2 = (aref_voltage*readvalue)/4096;
 Serial.println(voltage2);
 readvalue = read_adc(3);
voltage3 = (aref_voltage*readvalue)/4096;
 Serial.println(voltage3);
 readvalue = read_adc(4);
voltage4 = (aref_voltage*readvalue)/4096;
Serial.println(voltage4);
 readvalue = read_adc(5);
voltage5 = (aref_voltage*readvalue)/4096;
Serial.println(voltage5);
Serial.println(" ");


//appending adc values to datastring
 String dataString ="";
 dataString += String(voltage0);
  dataString += ",";
 dataString += String(voltage1);
  dataString += ",";
 dataString += String(voltage2);
  dataString += ",";
 dataString += String(voltage3);
 dataString += ",";
 dataString += String(voltage4);
  dataString += ",";
 dataString += String(voltage5);
  dataString += ",";
  Serial.println(dataString);
 

 SD.begin(chipSelect);      //SD card initialize
 
 File dataFile = SD.open("FDR.csv", FILE_WRITE);    //create file and perform write func
   
     // if the file is available, write to it:
  if (dataFile)
  {

    dataFile.println(Time);
   
    dataFile.println(date);

    dataFile.println(dataString);
   
   dataFile.close();
   
 
  }
 
 digitalWrite(chipSelect,LOW);    //disable SD card
 delay(250);
 
}

haziqamjad

What device is connected to pin 0 and 1, or is that just a representation of the USB serial monitor.
What is VREF connected to.
What battery voltage, and is it connected to something low impedance.
Leo..
At pin 0 and 1, it is a serial monitor
Vref is connected to 5V
"What battery voltage, and is it connected to something low impedance.?"--i dont undersatand what u are saying

Wawa

Pin 0 and 1 are internally connected to the USB<>Serial chip of the Uno and shouldn't be used for anything else.
Use SoftwareSerial on two different pins if you are using a second/external serial device.

The (potentially dirty) 5volt supply pin of an Uno is not really suitable as voltage reference for a 12-bit A/D.
What are you trying to measure.

The inputs of an A/D must be connected to something solid (>= 10k impedance).
Floating pins will return random values.
Leo..

haziqamjad

Pin 0 and 1 are internally connected to the USB<>Serial chip of the Uno and shouldn't be used for anything else.
Use SoftwareSerial on two different pins if you are using a second/external serial device.

The (potentially dirty) 5volt supply pin of an Uno is not really suitable as voltage reference for a 12-bit A/D.
What are you trying to measure.

The inputs of an A/D must be connected to something solid (>= 10k impedance).
Floating pins will return random values.
Leo..
voltage reference for a 12-bit A/D is not 5 V supply pin of uno. A separate dc voltage source is actually the reference which is named as Vref. The input pins of ADC are connected to a dc voltage source of 3.7V named as U1 (in blue color). It is just for simulation and checking whether i am getting correct values. I still dont inderstand what do you mean by "The inputs of an A/D must be connected to something solid (>= 10k impedance).Floating pins will return random values."


jremington

#11
Jun 23, 2018, 04:58 pm Last Edit: Jun 23, 2018, 04:58 pm by jremington
Quote
I still dont inderstand what do you mean by
Time to do some reading. Start by googling "floating inputs".

Strings are still in your code, waiting to crash it. What don't you understand about the phrase "get rid of them"?

Code: [Select]
//appending adc values to datastring
 String dataString ="";
 dataString += String(voltage0);
  dataString += ",";
 dataString += String(voltage1);
  dataString += ",";
 dataString += String(voltage2);
  dataString += ",";
 dataString += String(voltage3);
 dataString += ",";
 dataString += String(voltage4);
  dataString += ",";
 dataString += String(voltage5);
  dataString += ",";
  Serial.println(dataString);

haziqamjad

i tested the code without strings but the problem was still the same. I know about the floating inputs but i don't think the input is "floating" because i have connected a dc voltage supply to it. Anyways i have posted the code without strings
Code: [Select]

//This code performs datalogging of an external adc on sd card
//MCP3208 is used for reading 6 analog channels
//This data is then appended in string named dataString
//dataString alongwith time and date are logged in a csv file

#include <Wire.h>
#include <RTClib.h>
#include <SPI.h>
#include <SD.h>

RTC_DS1307 RTC;




#define SELPIN 10 //Selection Pin
#define DATAOUT 11//MOSI
#define DATAIN  12//MISO
#define SPICLOCK  13//Clock
#define aref_voltage 5
#define chipSelect  9//CS for Sd card is PB1 or PIN 9


float readvalue,voltage0,voltage1,voltage2,voltage3,voltage4,voltage5;

void setup(){
 //set pin modes
 pinMode(SELPIN, OUTPUT);
 pinMode(chipSelect, OUTPUT);
 pinMode(DATAOUT, OUTPUT);
 pinMode(DATAIN, INPUT);
 pinMode(SPICLOCK, OUTPUT);


 //disable device to start with
 
 digitalWrite(SELPIN,HIGH);
 digitalWrite(DATAOUT,LOW);
 digitalWrite(SPICLOCK,LOW);
 


 Serial.begin(9600);
 Wire.begin();
 RTC.begin();

// following line sets the RTC to the date & time this sketch was compiled
 RTC.adjust(DateTime(__DATE__, __TIME__));

}


  float read_adc(int channel)
{
  int adcvalue = 0;
  byte commandbits = B11000000; //command bits - start, mode, chn (3), dont care (3)

  //allow channel selection
  commandbits|=((channel-1)<<3);
  digitalWrite(chipSelect,LOW);
  digitalWrite(SELPIN,LOW); //Select adc
  // setup bits to be written
  for (int i=7; i>=3; i--){
  digitalWrite(DATAOUT,commandbits&1<<i);
  //cycle clock
  digitalWrite(SPICLOCK,HIGH);
  digitalWrite(SPICLOCK,LOW); 
   
}

  digitalWrite(SPICLOCK,HIGH);    //ignores 2 null bits
  digitalWrite(SPICLOCK,LOW);
  digitalWrite(SPICLOCK,HIGH); 
  digitalWrite(SPICLOCK,LOW);

  //read bits from adc
  for (int i=11; i>=0; i--){
  adcvalue+=digitalRead(DATAIN)<<i;
  //cycle clock
  digitalWrite(SPICLOCK,HIGH);
  digitalWrite(SPICLOCK,LOW);
  }
  digitalWrite(SELPIN, HIGH); //turn off device
  return adcvalue;
}



void loop() {
 


DateTime now = RTC.now();
int day = now.day();
int month = now.month();
int year = now.year();
int hour = now.hour();
int minute = now.minute();
int second = now.second();
 //String slash = "/";
 //String colon = ":";
 //String date = day + slash + month + slash + year;
 //String Time = hour + colon + minute + colon + second;
 Serial.println(day);
 Serial.println(month);
 Serial.println(year);

  //reading adc
   readvalue = read_adc(0);
   voltage0 = (aref_voltage*readvalue)/4096;
Serial.println(voltage0);
  readvalue = read_adc(1);
voltage1 = (aref_voltage*readvalue)/4096;
 Serial.println(voltage1);
 readvalue = read_adc(2);
voltage2 = (aref_voltage*readvalue)/4096;
 Serial.println(voltage2);
 readvalue = read_adc(3);
voltage3 = (aref_voltage*readvalue)/4096;
 Serial.println(voltage3);
 readvalue = read_adc(4);
voltage4 = (aref_voltage*readvalue)/4096;
Serial.println(voltage4);
 readvalue = read_adc(5);
voltage5 = (aref_voltage*readvalue)/4096;
Serial.println(voltage5);
Serial.println(" ");

/*
//appending adc values to datastring
 String dataString ="";
 dataString += String(voltage0);
  dataString += ",";
 dataString += String(voltage1);
  dataString += ",";
 dataString += String(voltage2);
  dataString += ",";
 dataString += String(voltage3);
 dataString += ",";
 dataString += String(voltage4);
  dataString += ",";
 dataString += String(voltage5);
  dataString += ",";
  Serial.println(dataString);
 */

 SD.begin(chipSelect);      //SD card initialize
 
 File dataFile = SD.open("FDR.csv", FILE_WRITE);    //create file and perform write func
   
     // if the file is available, write to it:
  if (dataFile)
  {

    //dataFile.println(Time);
   
    //dataFile.println(date);

    dataFile.println("This is a test");
   
   dataFile.close();
   
 
  }
 
 digitalWrite(chipSelect,LOW);    //disable SD card
 delay(250);
 
}

jremington

#13
Jun 24, 2018, 05:41 pm Last Edit: Jun 24, 2018, 06:23 pm by jremington
Take out the SD card stuff and try again.

It is a very bad idea to open the SD file every time through the loop() function. Open it once in setup() and close it when you are done logging.

haziqamjad

Take out the SD card stuff and try again.

It is a very bad idea to open the SD file every time through the loop() function. Open it once in setup() and close it when you are done logging.
I took out the sd.begin and sd.open from loop and put it in the setup but it had the same results. As far as i can understand, the problem is that sd card and mcp3208 share the same spi lines. Therefore, in the code, when only mcp3208 is working, correct output is shown but when sdcard initialises, may be it creates problem for the mcp3208???

Go Up