Current and voltage sensing - sampling frequency: 6.25kHz

**Dear all, **

I provide a code for the acquisition of current and voltage data at a frequency of 6.25 kHz (adjustable). The code is the one that corresponds to the description given in this link.

Design of an Electricity Consumption Measurement System for Non Intrusive Load Monitoring - Archive ouverte HAL

#include <SPI.h>
#include <SD.h>
#include <Arduino.h>
#include <RTCZero.h>

#include <Bounce2.h>
// Include the Bounce2 library found here :
// GitHub - thomasfredericks/Bounce2: Debouncing library for Arduino and Wiring

#include "avdweb_SAMDtimer.h"
// SAMD21 Timer library for the SAM15x15 and Arduino Zero
// SAMD21 Timer
// SAMD21 Timer library for the Arduino Zero - Libraries - Arduino Forum

#include "Albert.h"
// Fast ADC library
// http://www.avdweb.nl/arduino/libraries/fast-10-bit-adc.html

Sd2Card card;

#define TRANSMISSIONSPEED 115200

#define BUTTON1_PIN 4
#define BUTTON2_PIN 5

#define AnalogPinU A1 // Analog Channel for voltage acquisition
#define AnalogPinI A2 // Analog Channel for current acquisition
#define BUFFSIZE 510 // 512/3=170.6666 or 510/3 = 170 --> 3 bytes
#define Te 200 // Aquisition period in µs //Fe= 2000 Hz

#define InformationBlockNumber 1

//------------------------------------------------------------------------------
void ISR_acquisition(struct tc_module *const module_inst); // This is just a prototype
//------------------------------------------------------------------------------

boolean start_acq, SD_init, SD_transfer, success, MyDebug = true;

byte dataUI, dateByte1, dateByte2, dateByte3, dateByte4, NumberOfAcquisitions;
uint8_t Data[2][510], DataSD[510], InformationBlock[512];

int i, dataU0_int, dataI0_int, dataU1_int, dataI1_int, LineIndex, SD_LineIndex, ColIndex;
int ColBlock1 = 1;
long NumberOfBlocks, blockNumberR, FirstBlockNumberW, blockNumberW, LastblockNumber, blockIndicatif;

String CurrentDate, CurrentTime;
char date[8];
Bounce debouncer1 = Bounce(); // Instantiate two Bounce objects
Bounce debouncer2 = Bounce();

RTCZero rtc;
SAMDtimer timer = SAMDtimer(3, ISR_acquisition, Te, 0); // ISR ISR_timer4, 1Hz (0.5s on, 0.5s off), timer is disabled

//------------------------------------------------------------------------------

void Dateformat(char const *date, char *buff) {
int month, day, year;
static const char month_names = "JanFebMarAprMayJunJulAugSepOctNovDec";
sscanf(date, "%s %d %d", buff, &day, &year);
month = (strstr(month_names, buff) - month_names) / 3 + 1;
sprintf(buff, "%02d%02d%d", day, month, year);
}

//------------------------------------------------------------------------------

void setCompileTimeDate() {

String timeString = TIME; // get the time from the compiler:
byte timeArray[3]; // byte array for the elements of the time
int t = 0; // array counter

while (timeString.length() > 0) { // iterate over the string, reading the first number then removing it from the string, until the string is gone:
byte nextNumber = timeString.toInt(); // read beginning of string, convert to integer:
timeArray[t] = nextNumber; // save number in the array:
timeString.remove(0, 3); // remove the first three chars of the array:
t++;
}

Dateformat(DATE, date);
byte dateArray[3]; // array for the elements of the time
String Empty = "";
dateArray[0] = (String(Empty + date[0] + date[1])).toInt();
dateArray[1] = (String(Empty + date[2] + date[3])).toInt();
dateArray[2] = (String(Empty + date[6] + date[7])).toInt();

rtc.setTime(timeArray[0], timeArray[1], timeArray[2]);
rtc.setDate(dateArray[0], dateArray[1], dateArray[2]);
}

//------------------------------------------------------------------------------

void ISR_acquisition(struct tc_module *const module_inst) {

int dataU = analogReadFast(AnalogPinU); dataU = 257;
int dataI = analogReadFast(AnalogPinI); dataI = 514;

if (ColIndex % 5 == 0) {
dataUI = dataU & 0B11;
dataUI = (dataUI << 2) | (dataI & 0B11);
Data[LineIndex][ColIndex] = dataU >> 2; ColIndex = ColIndex + 1;
Data[LineIndex][ColIndex] = dataI >> 2; ColIndex = ColIndex + 1;
} else if (ColIndex % 5 == 2) {
dataUI = (dataUI << 2) | (dataU & 0B11);
dataUI = (dataUI << 2) | (dataI & 0B11);
Data[LineIndex][ColIndex] = dataU >> 2; ColIndex = ColIndex + 1;
Data[LineIndex][ColIndex] = dataI >> 2; ColIndex = ColIndex + 1;
Data[LineIndex][ColIndex] = dataUI; ColIndex = ColIndex + 1;
}

if (ColIndex == BUFFSIZE) {
SD_LineIndex = LineIndex; LineIndex = 1 - LineIndex;
ColIndex = 0;

if (SD_transfer) {
  Serial.println(F("interruptions stopped."));
  timer.enableInterrupt(0);                          // disable ISR_acquisition
} else
  SD_transfer = true;

}
}
//------------------------------------------------------------------------------

void CodeDate() {
int Day = rtc.getDay(); int Month = rtc.getMonth(); int Year = rtc.getYear();
int Hours = rtc.getHours(); int Minutes = rtc.getMinutes(); int Seconds = rtc.getSeconds();
dateByte1 = (Year << 2) | ((Month & 0b1100) >> 2);
dateByte2 = ((Month & 0b11) << 6) | ((Day & 0b11111) << 1) | ((Hours & 0b10000) >> 4);
dateByte3 = ((Hours & 0b1111) << 4) | ((Minutes & 0b111100) >> 2);
dateByte4 = ((Minutes & 0b11) << 6) | (Seconds & 0b111111);
}
//------------------------------------------------------------------------------

void DecodeDL(int index) { /* Decode Date and Lastblock address */
long LastBlock;
index = (index - 1) * 8 + 1;
int Year = InformationBlock[index ] >> 2;
int Month = ((InformationBlock[index ] & 0B00000011) << 2) | ((InformationBlock[index + 1] & 0B11000000) >> 6);
int Day = ((InformationBlock[index + 1] & 0B00111110) >> 1);
int Hours = ((InformationBlock[index + 1] & 0B00000001) << 4) | ((InformationBlock[index + 2] & 0B11110000) >> 4);
int Minutes = ((InformationBlock[index + 2] & 0B00001111) << 2) | ((InformationBlock[index + 3] & 0B11000000) >> 6);
int Seconds = InformationBlock[index + 3] & 0B00111111;

LastBlock = InformationBlock[index + 4];
LastBlock = LastBlock << 8 | InformationBlock[index + 5];
LastBlock = LastBlock << 8 | InformationBlock[index + 6];
LastBlock = LastBlock << 8 | InformationBlock[index + 7];

Serial.print("Date: "); Serial.print(Day); Serial.print("/"); Serial.print(Month); Serial.print("/"); Serial.print(Year); Serial.print(" ");
Serial.print("Time: "); Serial.print(Hours); Serial.print(":"); Serial.print(Minutes); Serial.print(":"); Serial.print(Seconds); Serial.print(" ");
Serial.print("Last Block: "); Serial.print(LastBlock); Serial.println(" ");
}
//------------------------------------------------------------------------------

void setup() {
if (MyDebug) {
Serial.begin(TRANSMISSIONSPEED);
delay(10000);
Serial.println(F("Application started"));
pinMode(SDCARD_SS_PIN, OUTPUT); Serial.print("SDCARD_SS_PIN="); Serial.println(SDCARD_SS_PIN);
}

card.init(SPI_HALF_SPEED, SDCARD_SS_PIN);

NumberOfBlocks = card.cardSize(); Serial.print("Total number of blocks="); Serial.println(NumberOfBlocks);

pinMode(BUTTON1_PIN, INPUT_PULLUP);
digitalWrite(BUTTON1_PIN, HIGH);
debouncer1.attach(BUTTON1_PIN);
debouncer1.interval(5);

pinMode(BUTTON2_PIN, INPUT_PULLUP);
digitalWrite(BUTTON2_PIN, HIGH);
debouncer2.attach(BUTTON2_PIN);
debouncer2.interval(5);

Serial.println(F("Setup buttons"));

rtc.begin();
setCompileTimeDate();
Serial.println("RTC initialized");

start_acq = false;

if (!card.readBlock(InformationBlockNumber, InformationBlock)) { //try to read block
Serial.println("Unable to read a block");
}

NumberOfAcquisitions = InformationBlock[0];
if (NumberOfAcquisitions == 0) {
FirstBlockNumberW = 2;
}
else {
int index = (NumberOfAcquisitions - 1) * 8 + 5;
FirstBlockNumberW = InformationBlock[index + 4];
FirstBlockNumberW = FirstBlockNumberW << 8 | InformationBlock[index + 5];
FirstBlockNumberW = FirstBlockNumberW << 8 | InformationBlock[index + 6];
FirstBlockNumberW = FirstBlockNumberW << 8 | InformationBlock[index + 7];
FirstBlockNumberW = FirstBlockNumberW + 1;
}

Serial.print("First block number available = "); Serial.print(FirstBlockNumberW);
blockNumberW = FirstBlockNumberW;
Serial.println("System ready press button 1 to start the acquisition");
}

//------------------------------------------------------------------------------

void loop() {
if (start_acq && SD_transfer) {
uint8_t (&temp)[BUFFSIZE] = Data[SD_LineIndex];
success = card.writeBlock(blockNumberW, temp);
if (!success) {
Serial.println("unable to write a block");
}
//Serial.print("blockNumber= 0x"); Serial.print(blockNumber, HEX); Serial.print(" "); printBlock(DataIU[SD_LineIndex]);
blockNumberW = blockNumberW + 1;
SD_transfer = false ;
} else if (start_acq && SD_init) {
SD_init = false ;
SD_transfer = true ;
} else if (debouncer1.update() && debouncer1.fell()) {
start_acq = !start_acq;
if (start_acq) {
Serial.println("button 1 pressed, starting acquisition ");
NumberOfAcquisitions++;

  CodeDate();
  timer.enableInterrupt(1); // enable ISR_acquisition
  LineIndex = 0;
  ColIndex  = 0;
  SD_transfer = false;
} else {
  LastblockNumber = blockNumberW - 1;
  InformationBlock[0] = NumberOfAcquisitions;

  InformationBlock[ColBlock1] = dateByte1; ColBlock1 = ColBlock1 + 1;
  InformationBlock[ColBlock1] = dateByte2; ColBlock1 = ColBlock1 + 1;
  InformationBlock[ColBlock1] = dateByte3; ColBlock1 = ColBlock1 + 1;
  InformationBlock[ColBlock1] = dateByte4; ColBlock1 = ColBlock1 + 1;

  InformationBlock[ColBlock1] = (LastblockNumber >> 24) & 0xFF; ColBlock1 = ColBlock1 + 1;
  InformationBlock[ColBlock1] = (LastblockNumber >> 16) & 0xFF; ColBlock1 = ColBlock1 + 1;
  InformationBlock[ColBlock1] = (LastblockNumber >> 8) & 0xFF; ColBlock1 = ColBlock1 + 1;
  InformationBlock[ColBlock1] = LastblockNumber & 0xFF; ColBlock1 = ColBlock1 + 1;

  if (!card.writeBlock(blockIndicatif, InformationBlock)) {
    Serial.println("unable to write a block");
  }
  timer.enableInterrupt(0);  // disable ISR_acquisition
  Serial.println("button 1 pressed, stopping acquisition ");
  //Serial.print("LastblockNumber= "); Serial.println(LastblockNumber);
}

} else if ( debouncer2.update() && debouncer2.fell()) {
Serial.println(" ");
Serial.println("Début affichage");
if (!card.readBlock(InformationBlockNumber, InformationBlock)) { //try to read block
Serial.println("unable to read a block");
}
else {
Serial.print("blockNumber= "); Serial.print(InformationBlockNumber); Serial.print(": ");
Serial.print("Push button counter: "); Serial.println(InformationBlock[0]);
for (i = 1; i <= InformationBlock[0]; i++) {
DecodeDL(i);
}
//acquisitionLog(InformationBlock[0], InformationBlock);
Serial.println();
}
/for (ColIndex = 0; ColIndex < 512;ColIndex++){
Serial.print(InformationBlock[ColIndex]);
Serial.print("(");Serial.print(ColIndex);Serial.print(") "); }
Serial.println();
/
for (blockNumberR = InformationBlockNumber; blockNumberR <= LastblockNumber; blockNumberR++) {
if (!card.readBlock(blockNumberR, DataSD)) { //try to read block
Serial.println("unable to read a block");
} else {
Serial.print("blockNumber= "); Serial.print(blockNumberR); Serial.print(": ");
for (ColIndex = 0; ColIndex < BUFFSIZE; ) {
byte dataU0 = DataSD[ColIndex]; ColIndex = ColIndex + 1;
byte dataI0 = DataSD[ColIndex]; ColIndex = ColIndex + 1;
byte dataU1 = DataSD[ColIndex]; ColIndex = ColIndex + 1;
byte dataI1 = DataSD[ColIndex]; ColIndex = ColIndex + 1;
byte dataIU = DataSD[ColIndex]; ColIndex = ColIndex + 1;
dataU0_int = (dataU0 << 2) | ((dataIU & 0B11000000) >> 6) ;
dataI0_int = ((dataI0 << 2 ) | ((dataIU & 0B00110000) >> 4));
dataU1_int = (dataU1 << 2) | ((dataIU & 0B00001100) >> 2) ;
dataI1_int = ((dataI1 << 2 ) | ((dataIU & 0B00000011)));
Serial.print(dataU0_int); Serial.print(" ; "); Serial.print(dataI0_int); Serial.print(" ");
Serial.print(dataU1_int); Serial.print(" ; "); Serial.print(dataI1_int); Serial.print(" ");
Serial.print(" ");
}
Serial.println();
}
}
//InformationBlockNumber = LastblockNumber + 1;
Serial.println("Fin affichage");
}
}