/*
28 July 2020
This code runs on Teensy3.5 which has a battery backed RTC. This code
must be compiled with the Teensy version of SPI and Wire libraries..
This is a bare bone code to just check the ADC functionality and writing to SD Card.
Code for Auto update of RTC from PC time base is included.
Auto file name generation is done.
Other aspects like facility to start / stop logging, scaling of ADC channels etc
need to be built in.
29 July 2020
Refine the code removing the String object. Also use Arrays to handle 8 ch in a FOR loop.
Code a Fixed duration LED flash to denote SD card write.OK
*/
#include <ADC.h>
#include <ADC_util.h>
#include <SPI.h>
#include <SD.h>
#include <TimeLib.h>
#define VREF 3.3
#define resolution (VREF/((pow(2,12))-1))
const int chipSelect = BUILTIN_SDCARD;
const int readPin[8] = {A0, A1, A2, A3, A4, A5, A6, A7};
const int LED = 13;
bool ledState ;
double voltage[8];
unsigned long readAdcMs = millis();
unsigned long ledOnMs = millis();
unsigned long writeSDMs = millis();
unsigned long readAdcInterval = 1000; // How often to read ADC
unsigned long ledOnInterval = 100; // How long the LED is on to denote SD write.
unsigned long writeSDInterval = 5000; // How often to write to SD
char filename[32];
char currentFile[32];
// Instantiate objects..
File sdFile;
ADC *adc = new ADC();
//OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
void setup() {
setSyncProvider(getTeensy3Time); // Set the Time library to use Teensy 3.5's RTC to keep time
for (int i = 0; i < 8 ; i++) {
pinMode(readPin[i], INPUT ); // Set all 8 adc inputs..
}
pinMode(LED, OUTPUT);
Serial.begin(9600);
while (!Serial); // Serial printing does not happen without this while loop delay !!
delay(500);
if (timeStatus() != timeSet) {
Serial.println("Unable to sync with the RTC");
}
else {
Serial.println("RTC has set the system time");
}
if (!SD.begin(chipSelect)) // Start the SD Card interface..
{
Serial.println( " SD Card Init failure !!");
while ( 1 == 1) {
ledState = !ledState ;
digitalWrite( LED, ledState);
delay(500); // Hang on here for Reset flashing the LED..
}
}
char filename[] = "T35LOG00.CSV"; // Create a logging file
for (uint8_t i = 0; i < 100; i++) {
filename[6] = i / 10 + '0';
filename[7] = i % 10 + '0';
if (! SD.exists(filename)) {
sdFile = SD.open(filename, FILE_WRITE); // Only open a new file if it doesn't exist
if (sdFile) {
strcpy(currentFile, filename); // Get a copy of the active filename
sdFile.close();
}
else {
Serial.println(" Error Opening SD Card" );
digitalWrite( LED, HIGH);
while (1 == 1); // Wait for reset
}
break;
}
}
// Configure the ADC0
adc->adc0->setReference(ADC_REFERENCE::REF_3V3);
adc->adc0->setAveraging(8);
adc->adc0->setResolution(12);
adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::MED_SPEED);
adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::MED_SPEED);
}
//OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
void loop()
{
getTimeFromPC();
readAnalogValues();
logToMicroSD();
ledForSDWrite();
}
//OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
//OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
void readAnalogValues() // Function to read analog values / scale them / save them to SD File to write later
{
if ( millis() - readAdcMs > readAdcInterval ) {
readAdcMs = millis();
sdFile.print(now());
sdFile.print(',');
for (int i = 0 ; i < 8; i++)
{
voltage[i] = adc->adc0->analogRead(readPin[i]) * resolution ;
sdFile.print(voltage[i], 3);
delay(2);
if (i < 7)
sdFile.print(',');
}
sdFile.println();
}
}
//.............................................
void logToMicroSD() {
if ( millis() - writeSDMs > writeSDInterval) {
writeSDMs = millis();
sdFile.close(); // Transfer the logged data from buffer to SD Card
digitalClockDisplay();
ledState = HIGH ;
ledOnMs = millis();
digitalWrite(LED, HIGH); // Enable the LED .. will switch off after a fixed time.
Serial.println(now());
for (int i = 0 ; i < 8; i++)
{
Serial.println(voltage[i], 3); // Print on monitor..
}
sdFile = SD.open(currentFile, FILE_WRITE); // Open the SDfile for the next session
if (!sdFile ) {
Serial.println(" Error Opening SD Card" );
digitalWrite( LED, HIGH);
while (1 == 1); // Wait for reset
}
}
}
//.............................................
void digitalClockDisplay()
{
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
Serial.print(month());
Serial.print(" ");
Serial.print(year());
Serial.println();
}
//..............................................
time_t getTeensy3Time()
{
return Teensy3Clock.get();
}
//...............................................
void printDigits(int digits) // Utility clock display: prints preceding colon and leading 0
{
Serial.print(":");
if (digits < 10)
Serial.print('0');
Serial.print(digits);
}
//.............................................
void getTimeFromPC ()
{
if (Serial.available() )
{
time_t t = processSyncMessage(); // Try to synch with PC clock..
if (t != 0)
{
Teensy3Clock.set(t); // Set the RTC
setTime(t);
}
}
}
//.............................................
#define TIME_HEADER "T" // Header tag for serial time sync message
unsigned long processSyncMessage()
{
unsigned long pctime = 0L;
const unsigned long DEFAULT_TIME = 1577836800; // Jan 1 2020
if (Serial.find(TIME_HEADER))
{
pctime = Serial.parseInt();
return pctime;
if ( pctime < DEFAULT_TIME) // Check the value is a valid time (greater than Jan 1 2013)
{
pctime = 0L; // Return 0 to indicate that the time is not valid
}
}
return pctime;
}
//............................................
void ledForSDWrite() {
if ( ledState) {
if (millis() - ledOnMs > ledOnInterval) {
digitalWrite(LED, LOW);
ledState = LOW;
}
}
}
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$