Hello,
As I still am not allowed to add files, I will try to add my codes and libraries in the message.
First the program code. This code works fine, BUT if I comment the line 561 "asm("nop");" then the programm crashes if I turn the rotary encoder button!
/*
Programme pour montage multi-usages à base d'Arduino Nano
par Jean-Paul Gendner, F5BU, 2021-07
Ce programme permet simultanément et indépendament l'utilisation de :
- Serial.print (faisant appel à la bibliothèque Arduino)
- un afficheur LCD parallèle (en utilisant la bibliothèque LiquidCrystal) ou/et
un afficheur LCD I2C (en utilisant la bibliothèque LiquidCrystal_I2C)
- un convertisseur analogique numérique 24 bits ADS1220 (Protocentral_ADS1220_g)
- un convertisseur numérique analogique 12 bits MCP4821 (MCP4821_g)
- la bibliothèque SPI (utilisée pour la gestion des convertisseurs et carte SD)
- du timer2 géré par interruptions
- un Encodeur rotatif avec bouton poussoir SW dont les transitions
sont gérées par interruptions (D2 et D3)
- une horloge temps réel (RTC-DS3231) gérée par I2C (Wire, RTClib)
- un module pour carte Micro SD (SD)
| pin label | Pin Function |Arduino Connection|
ADS1220
|-----------------|:--------------------:|-----------------:|
| DVDD | Digital VDD | +5V |
| DGND | Digital Gnd | GND |
| AN0-AN3 | Analog Input | Analog Inputs |
| AVDD | Analog VDD | +2,5V or 5V |
| AGND | Analog Gnd | -2,5V or GND |
| DRDY | Data ready Output pin| A5 |
| CS | Chip select barre | A3 |
ADS1220, MCP4821 et SD (SPI)
| MISO | Slave Out | D12 |
| MOSI | Slave In | D11 |
| SCLK | Serial Clock | D13 |
MCP4821 (SPI)
| CS | Chip select barre | D10 |
| SHDN barre | Shutdown | +5V |
| LDAC barre | Latching DAC | GND |
SD (SPI)
| CS | Chip select barre | D9 |
Encodeur rotatif avec interrupteur
| SW | Switch | D4 |
| DT | data pin for I2C | D3 |
| CLK | clock pin for I2C | D2 |
Horloge RTC (I2C)
| SDA | Switch | A4 |
| SCL | Switch | A5 |
LCD (I2C)
| SDA | Switch | A4 |
| SCL | Switch | A5 |
Les bibliothèques pour l'ADS1220 et le MCP4882 sont d'origines des bibliothèques du MIT,
et modifiées par l'auteur.
The MIT software are licensed under the MIT License(http://opensource.org/licenses/MIT).
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
For information on how to use, visit https://github.com/Protocentral/Protocentral_ADS1220
ADS1220 Offset (µV) mesuré le 2021-05-14
G= 1 PE=2048mV 6 1,46
G= 2 PE=1024mV 0 0,00
G= 4 PE= 512mV 12 0,73
G= 8 PE= 256mV -11 -0,34
G= 16 PE= 128mV -255 -3,89
G= 32 PE= 64mV -715 -5,46
G= 64 PE= 32mV -1887 -7,20
G=128 PE= 16mV -4425 -8,44
*/
#define Duree_AD 0 // durée en ms de l'AD ou 0 pour durée infinie
#define Int_Mes_Temp 0 // Interval mesures Température en ms
#define UGain -1 // Gain A/D : -1=>Auto, 1, 2, 4, 8, 16, 32, 64, 128
#define Rate DR_20SPS // vitesse A/D sps : 20,45,90,175,330,600,1000
#define MoyBit 3 // 0->1, 1->2, 2->4, 3->8, 4->16, 5->32, 6->64, 7->128, 8->256, 9->512
#define RR5V 5.68 // Rapport résistances pour mesure du 5V (1er CI)
#define RR12V 23.6 // Rapport résistances pour mesure du 12V (Vin)
//#define RR5V 5.7 // Rapport résistances pour mesure du 5V (montage proto)
//#define RR12V 22.6 // Rapport résistances pour mesure du 12V (Vin)
#define Debug 0 // 2 pour Calibration; 1 pour tous les messages Serial.print sur moniteur série
#define LCD 'I' // P pour parralèlle, I pour I2C, Mettre en commentaire si pas de LCD
#define ADS1220_Temp // Mettre en commentaire pour ne pas utiliser la température de l'ADS1220
#define EEPROM_use // Mettre en commentaire pour ne pas utiliser
#define Timer2 // Mettre en commentaire pour ne pas utiliser
#define MCP4821_P // Mettre en commentaire si non utilisé/présent
#define RTC_Present 1 // 0 si absent; 1 utilisation; -1 initialisation date heure
#define SD_Present // Mettre en commentaire si module Micro SD non utilisé
// LCD
#if defined LCD
#if LCD=='P'
// LCD paralèlle
#include <LiquidCrystal.h>
#define LCDcol 16 // Nombre de colonnes LCD
#define LCDrow 2 // Nombre de lignes LCD
const int rs = 9, en = 8, d4 = 7, d5 = 6, d6 = 5, d7 = 4;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
#else
// LCD I2C
#include <LiquidCrystal_I2C.h>
#define LCDcol 20 // Nombre de colonnes LCD
#define LCDrow 4 // Nombre de lignes LCD
LiquidCrystal_I2C lcd(0x27, LCDcol, LCDrow);
#endif
#endif
String str;
#if defined ADS1220_Temp
String strTemp;
#endif
// EEPROM de l'Arduino
// 0-31 Offset du CAN pour les 8 valeurs de gain
#if defined EEPROM_use
#include <EEPROM.h>
#define EadOffset 0 //adresse du tableau des valeurs d'offset fonction du gain
#endif
// CAN de l'Arduino
#define AVref 1.12 // Arduino internal VRef typical =1.1V
int16_t AValue;
// DEL
#define LED A1
// CAN ADS1220 24 bits
#include <SPI.h>
#include "Protocentral_ADS1220_g.h"
#define VREF 2048 // en mVInternal reference of 2.048V
#define FULL_SCALE (((int32_t)1<<23)-1) // 8 388 607
#define Val_lsb VREF/FULL_SCALE // 0.00024414 pour PGA=1
#define ADS1220_DRDY_PIN A2
#define ADS1220_CS_PIN A3
#define nMoy (1<<MoyBit) // Nombre de mesures pour faire une moyenne
#define NbSatAuto 5 // Nombre de mesures Saturantes Autorisées sur nMoy
// DAC MCP4821 12 bits
#if defined MCP4821_P
#include <SPI.h>
#include "MCP4821_g.h"
#define DAC_GM 0x3000 // Gain et Masque : 0x1000 pour G=2, 0x3000 pour G=1
#endif
#define DAC_PIN_CS 10
// Encodeur avec bouton poussoir
#include <Encoder.h> // by Paul Stoffregen
// Change these two numbers to the pins connected to your encoder.
// Best Performance: both pins have interrupt capability
// Good Performance: only the first pin has interrupt capability
// Low Performance: neither pin has interrupt capability
Encoder myEnc(2, 3); // avoid using pins with LEDs attached
//Encoder myEnc(2, 5); // pour libérer la pin 3 pouvant générer des interruptions
int32_t oldPosition = -999;
int32_t newPosition;
#define SW 4
// Timer2
#if defined Timer2
#define T2_Counter int(256-125000/1000-.5) // preload timer = 256-16MHz/128/1000Hz -> défini la fréquence
int timer2_counter = T2_Counter;
#endif
// CAN 24 bits ADS1220
Protocentral_ADS1220 pc_ads1220;
int32_t OffsetG[8] = {0, 0, 0, 0, 0, 0, 0, 0};
byte GIndice;
int32_t adc_data;
int32_t sigma;
int32_t sigma0;
int32_t iad;
int32_t bit24;
byte PGA = 1; // Programmable Gain
float xfloat;
float x2float;
uint16_t NbSat = 0;
boolean AD_F = false;
boolean AD_F_F = false;
boolean Cal_F = false;
// CNA 12 bit MCP4821
#if defined MCP4821_P
MCP4821 dacChip;
volatile int16_t DAC16;
#endif
// Carte SD
#define SD_CS_PIN 9
#if defined SD_Present
#include <SPI.h>
#include <SD.h>
File myFile;
// change this to match your SD shield or module;
boolean SDOK = false;
char NomFichier[13] = {'T', 'e', 's', 't', '.', 't', 'x', 't', '\0'};
#endif
// RTC Real Time Clock
#if RTC_Present!=0
#include <Wire.h>
#include <RTClib.h>
RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Di", "Lu", "Ma", "Me", "Je", "Ve", "Sa"};
char cDateRTC[] = "YYYY-MM-DD";
char cHeureRTC[] = "HH:II:SS";
#endif
unsigned long MillisDebut; // max 49jours
#if defined ADS1220_Temp
unsigned long MillisTemp;
#endif
// * * * Setup * * * -------------------------------------------------------
void setup()
{
// Port COM
#if Debug!=0
Serial.begin(115200);
Serial.println();
#endif
// LED
pinMode(LED, OUTPUT);
// Encodeur et bouton poussoir
pinMode(SW, INPUT_PULLUP);
#if defined LCD
#if LCD=='P'
lcd.begin(LCDcol, LCDrow);
#else
lcd.init();
lcd.clear();
lcd.backlight(); // Make sure backlight is on
#endif
lcd.setCursor(2, 0);
// lcd.display();
lcd.print(F("F5BU"));
#endif
// Micro SD
#if defined SD_CS_PIN
pinMode(SD_CS_PIN, OUTPUT);
digitalWrite(SD_CS_PIN, HIGH);
#endif
// ADC
pinMode(ADS1220_CS_PIN, OUTPUT);
digitalWrite(ADS1220_CS_PIN, HIGH);
analogReference(INTERNAL);// référence de 1,1V +/- 10%
pc_ads1220.begin(ADS1220_CS_PIN, ADS1220_DRDY_PIN);
pc_ads1220.set_data_rate(Rate);
Set_Gain(1);
pc_ads1220.set_conv_mode_single_shot(); //Set Single shot mode
#if defined EEPROM_use
EEPROM.get(EadOffset, GIndice); // récupération du tableau d'offsets dans l'EEPROM
if (GIndice != 255) { // uniquement si une calibration a déjà été faite
for (int i = 0; i <= 7; i++) {
EEPROM.get(EadOffset + i * 4, OffsetG[i]);
}
}
#endif
// CNA
#if defined MCP4821_P
dacChip.begin( DAC_PIN_CS, DAC_GM );
DAC16 = 0; //0x800;
// dacChip.writedata16(DAC16); // initialisation de la valeur du DAC par valeur binaire
dacChip.setVoltage(1.2); // ou valeur en tension
#endif
// Timer2 initialisation pour une période de 1ms (f = 1000Hz)
#if defined Timer2
timer2_counter = T2_Counter; // preload timer = 256-16MHz/128/1000Hz
TCCR2A = 0;
TCCR2B = 0;
TCNT2 = timer2_counter; // preload timer
// TCCR2B |= (1 << CS21) | (1 << CS20); // 32 prescaler
TCCR2B |= (1 << CS22) | (1 << CS20); // 128 prescaler
#endif
// Gestion RTC
#if RTC_Present!=0
if (! rtc.begin()) {
Serial.println(F("Pas de RTC"));
#if LCDrow>=4
lcd.setCursor(9, 2);
lcd.print(F("Pas de RTC"));
#endif
} else {
// Mettre date heure pour première utilisation
#if RTC_Present==-1
if (rtc.lostPower()) {
#if Debug>=0
Serial.println(F("RTC lost power, lets set the time!"));
#endif
// Comment out below lines once you set the date & time.
// Following line sets the RTC to the date & time this sketch was compiled
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// OR sets the RTC with an explicit date & time
// for example to set January 27 2017 at 12:56 you would call:
// rtc.adjust(DateTime(2017, 1, 27, 12, 56, 0));
while (digitalRead(SW) = HIGH); {}
rtc.adjust(DateTime(2021, 8, 06, 16, 0, 0));
}
#endif
getDateHeure();
#if LCDrow>=4
lcd.setCursor(0, 2);
lcd.print(cDateRTC);
lcd.setCursor(11, 2);
lcd.print(cHeureRTC);
#endif
}
#endif
// Micro SD
#if defined SD_Present
pinMode(SD_CS_PIN, OUTPUT);
digitalWrite(SD_CS_PIN, 1);
if (!SD.begin(SD_CS_PIN)) {
#if Debug>=0
Serial.println(F("Pas de SD"));
#endif
#if defined LCD
#if LCDrow>=4
lcd.setCursor(0, 3);
lcd.print(F("Pas de SD"));
#endif
#endif
SDOK = false;
} else {
#if Debug>=0
Serial.println(F("SD OK"));
#endif
#if defined LCD
#if LCDrow>=4
lcd.setCursor(0, 3);
lcd.print(F("SD OK"));
#endif
#endif
SDOK = true;
}
#endif
// Gestion interruptions
// attachInterrupt(digitalPinToInterrupt(SW),ISRPoussoir,CHANGE);
// SPI.usingInterrupt(0);
// SPI.usingInterrupt(1);
SPI.usingInterrupt(255); // autorise les IT SPI durant ISR timer ?
// SPI.usingInterrupt(digitalPinToInterrupt(2));
// SPI.usingInterrupt(digitalPinToInterrupt(3));
//do {
#if defined ADS1220_Temp
MesAffTemp();
#endif
//}while((bit24<576 || bit24>1056) && ((millis()-MillisDebut)<10000));
//}while((bit24<576 || bit24>1056));
#if Debug>=0
Serial.print(F("CAN Conf: "));
PrintADS1220Config();
#endif
// Affichage tension 5V et éventuellement Vin
#if defined LCD
lcd.setCursor(0, 1);
lcd.print(F("5V="));
#endif
AValue = analogRead(A7);
AValue = analogRead(A7);
AValue = analogRead(A7);
AValue = analogRead(A7); // plusieurs lectures au début améliorent la précision
xfloat = AValue * (AVref / 1023.0) * RR5V;
#if defined LCD
lcd.print(xfloat, 1);
lcd.print(F("V"));
// adc_data=pc_ads1220.Read_SingleShot_SingleEnded_WaitForData(MUX_AIN2_AIN3);
lcd.setCursor(8, 1);
#endif
AValue = analogRead(A6);
AValue = analogRead(A6);
if (AValue > 208) {
xfloat = AValue * (AVref / 1023.0) * RR12V;
#if defined LCD
lcd.print(F(" <"));
lcd.print(xfloat, 1);
lcd.print(F("V"));
#endif
}
delay(4000);
// Configuration CAN
pc_ads1220.select_mux_channels(MUX_AIN0_AIN3); //Configure for differential measurement between AIN0 and AIN3
// pc_ads1220.select_mux_channels(MUX_AIN1_AIN3); //Configure for differential measurement between AIN1 and AIN3
pc_ads1220.set_data_rate(Rate);
#if UGain==-1
Set_Gain(1);
#else
Set_Gain(UGain);
#endif
pc_ads1220.set_conv_mode_continuous(); //set continous mode
pc_ads1220.Start_Conv(); //Start continuous conversion mode
// Activation Interruptions Timer2
#if defined Timer2
TIMSK2 |= (1 << TOIE2); // enable timer2 overflow interrupt
#endif
#if defined LCD
#if LCDrow>=4
lcd.setCursor(0, 2);
#else
lcd.setCursor(0, 1);
#endif
lcd.print(pc_ads1220.readRegister_gt(0), HEX);
lcd.print(F(" "));
lcd.print(pc_ads1220.readRegister_gt(1), HEX);
lcd.print(F(" "));
lcd.print(pc_ads1220.readRegister_gt(2), HEX);
lcd.print(F(" "));
lcd.print(pc_ads1220.readRegister_gt(3), HEX);
#endif
delay(200);
#if Debug>=0
Serial.print(F("Reg 0-3 : "));
PrintADS1220Config();
#endif
#if defined LCD
lcd.clear();
#endif
}
// * * * Boucle * * * * * * * * * * * * *
void loop()
{
if (AD_F == false) {
digitalWrite(LED, !digitalRead(LED));
}
#if defined SD_Present
if (AD_F_F) {
AD_F_F = false;
AD_F = true;
digitalWrite(LED, 1); // Début AD = LED allumée
#if RTC_Present!=0
getDateHeure();
#endif
OpenFile();
#if Debug==1 || RTC_Present!=0
Serial.print(F("Debut AD :"));
Serial.print(cDateRTC);
Serial.print(F(" "));
Serial.println(cHeureRTC);
#endif
}
#endif
if (Cal_F) {
if (!AD_F) { // Interdit une calibration durant une acquisition de données
Calibration();
}
Cal_F = false;
}
#if UGain==-1
do {}
while ((digitalRead(ADS1220_DRDY_PIN)) == HIGH);
adc_data = pc_ads1220.Read_Data_Samples(); // mesure avec gain=1
adc_data = adc_data - OffsetG[GIndice];
PGA_Auto();
#if Debug==1
Serial.print(F("G = 1"));
Serial.print(F("\t"));
Serial.print(adc_data);
Serial.print(F("\n"));
#endif
#endif
sigma = 0;
x2float = 0;
NbSat = 0;
for (int iad = 1; iad <= nMoy; iad++) {
#if LCDrow>=4
newPosition = myEnc.read();
if (newPosition != oldPosition) {
lcd.setCursor(2, 3);
oldPosition = newPosition;
lcd.print(-newPosition);
lcd.print(F(" "));
}
lcd.setCursor(0, 3);
if (digitalRead(SW) == LOW) {
lcd.print(F("P"));
switch (-newPosition) {
case 2:
#if defined SD_Present
if (SDOK && !AD_F) {
AD_F_F = true;
}
#endif
break;
case 4:
#if defined SD_Present
if (AD_F) {
AD_F = false;
}
#endif
break;
case -2:
Cal_F = true;
break;
}
} else {
lcd.print(F("N"));
}
#endif
do {}
while ((digitalRead(ADS1220_DRDY_PIN)) == HIGH);
adc_data = pc_ads1220.Read_Data_Samples(); // mesure avec gain=GPA
if (adc_data >= FULL_SCALE) {
NbSat = NbSat + 1;
}
if (adc_data <= -FULL_SCALE) {
NbSat = NbSat + 1;
}
adc_data = adc_data - OffsetG[GIndice];
sigma = sigma + adc_data;
// x2float=(float)x2float + (float)adc_data*(float)adc_data;
x2float = (float)x2float + (float)(adc_data << 1);
// if (Rmin>adc_data) { Rmin=adc_data; }
// if (Rmax<adc_data) { Rmax=adc_data; }
/* #if Debug==1
Serial.print(nMoy);
Serial.print(F(" "));
Serial.print(sigma);
Serial.print(F(" "));
Serial.println(x2float);
#endif*/
}
xfloat = 2 * (sqrt((abs(x2float - sigma * sigma) / nMoy) / (nMoy - 1))) / sqrt(nMoy);
// fois 1, 2 ou 3 pour Inteval de confiance à 68, 95 ou 99.7%
sigma = (sigma >> MoyBit); // moyenne
// sigma = sigma/nMoy; // pour des valeurs quelconques de nMoy
/* #if Debug==-1
// Serial.println(freeRam());
Serial.print(F("G="));
Serial.print(F("G="));
Serial.print(F("G="));
Serial.print(F("G="));
Serial.print(F("G="));
Serial.println(F("G="));
#endif*/
#if 1
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
#endif
#if Debug==1
Serial.print(F("G="));
Serial.print(PGA);
Serial.print(F("\t"));
Serial.print(sigma);
Serial.print(F("\t"));
if (NbSat >= NbSatAuto) {
Serial.print(F("Sat"));
}
Serial.print(convertToString(sigma));
Serial.print(convertToString(FULL_SCALE));
// Serial.print(convertTodBV(sigma));
Serial.print(F("\t"));
Serial.print(xfloat + '\t');
Serial.print(convertToString(xfloat) + '\t');
Serial.print(convertTodBV(sigma) + '\t');
#if defined ADS1220_Temp
Serial.println(strTemp);
#else
Serial.println();
#endif
// Serial.println();
#endif
#if defined LCD
lcd.setCursor(0, 0);
lcd.print(convertToString(sigma));
lcd.print(convertTodBV(sigma));
if (NbSat >= NbSatAuto) {
lcd.setCursor(0, 0);
lcd.print(F("S"));
}
lcd.setCursor(0, 1);
lcd.print(F("G"));
lcd.print(PGA);
lcd.print(F(" "));
lcd.setCursor(4, 1);
lcd.print(F(" IC95"));
// lcd.print(convertToString((Rmax-Rmin)/2,0));
#endif
str = convertToString(xfloat);
#if defined LCD
lcd.setCursor(9, 1);
// str.trim();
lcd.print(str);
#endif
#if defined SD_Present
#if RTC_present!=0
if (AD_F && (((millis() - MillisDebut) < Duree_AD) || Duree_AD == 0))
#else
if (AD_F)
#endif
{
// if the file opened okay, write to it:
if (myFile) {
#if RTC_present!=0
myFile.print(millis() - MillisDebut);
myFile.print(F(", "));
#endif
myFile.print(convertToString(sigma));
myFile.print(", " + str);
myFile.print(F(", "));
myFile.print(convertTodBV(sigma));
myFile.print(F(", "));
myFile.print(convertTodBV(xfloat));
myFile.print(F(", "));
#if defined ADS1220_Temp
myFile.println(strTemp);
// myFile.println(", "+strTemp); // nécessite plus de mémoire que 2 lignes ci-dessus
// myFile.flush(); // force l'écriture physique des données ATTENTION
// mauvais pour la carte SD
#else
myFile.println();
#endif
}
} else {
// if the file opened okay, write to it:
if (myFile) {
myFile.print(F("'Fin="));
#if RTC_present!=0
myFile.println(millis() - MillisDebut);
#else
myFile.println();
#endif
// myFile.flush(); // force l'écriture physique des données
// close the file:
myFile.close();
digitalWrite(LED, 0); // Fin AD = LED éteinte
#if Debug==1
Serial.println(F("Fin AD :"));
#endif
}
}
#endif
#if defined ADS1220_Temp
// if ((millis()-MillisTemp)>=Int_Mes_Temp) {
// noInterrupts();
//do {
MesAffTemp();
//} while(1);
// interrupts();
// }
#endif
#if UGain==-1
Set_Gain(1);
#endif
// delay(300);
}
// * * * FIN Boucle * * * * * * * * * * * * *
// * * * convertToMilliV * * * -------------------------------------------------------
float convertToMilliV(int32_t i32data)
{
return (float)(i32data * (float)Val_lsb / PGA);
}
// * * * ConvertToString * * * -------------------------------------------------------
String convertToString(int32_t i32data)
{
String strcts;
float floatcts;
floatcts = (float) i32data * Val_lsb / PGA;
if (abs(floatcts) >= 1000) {
strcts = (' ' + String(floatcts, 0) + "mV ");
if (floatcts > 0) {
strcts = ' ' + strcts;
}
}
else if (abs(floatcts) >= 100) {
strcts = (String(floatcts, 1) + "mV ");
if (floatcts > 0) {
strcts = ' ' + strcts;
}
}
else if (abs(floatcts) >= 10) {
strcts = (String(floatcts, 2) + "mV ");
if (floatcts > 0) {
strcts = ' ' + strcts;
}
}
else if (abs(floatcts) >= 1) {
strcts = (String(floatcts, 3) + "mV ");
if (floatcts > 0) {
strcts = ' ' + strcts;
}
}
else if (abs(floatcts) >= .1) {
strcts = (String(floatcts * 1000, 1) + "uV ");
if (floatcts > 0) {
strcts = " " + strcts;
}
if (strcts.length() == 8) {
strcts = " " + strcts;
}
else if (strcts.length() == 7) {
strcts = " " + strcts;
}
else if (strcts.length() == 6) {
strcts = " " + strcts;
}
}
else {
strcts = (String(floatcts * 1000, 2) + "uV ");
if (floatcts > 0) {
strcts = " " + strcts;
}
if (strcts.length() == 8) {
strcts = " " + strcts;
}
else if (strcts.length() == 7) {
strcts = " " + strcts;
}
else if (strcts.length() == 6) {
strcts = " " + strcts;
}
}
return (strcts);
}
// * * * convertTodBV // * * * * * * * * *
String convertTodBV(int32_t i32data)
{
float floatctd = (float) i32data * Val_lsb / PGA; // U crête en mvolts
if (abs(floatctd) >= 2047) {
floatctd = 20 * (log10(abs(floatctd))) - 60; // en dBV
str = (String(floatctd, 1) + ">>> ");
}
else if (abs(floatctd) <= 0.002) {
if (floatctd != 0) {
floatctd = 20 * (log10(abs(floatctd))) - 60; // en dBV
str = (' ' + String(floatctd, 0) + "<<< ");
}
else {
str = (" -180<<< ");
}
}
else {
floatctd = 20 * (log10(abs(floatctd))) - 60; // en dBV
str = (String(floatctd, 1) + "dBV ");
}
return (str);
}
/*// * * * convertTodBm * * * -------------------------------------------------------
String convertTodBm(int32_t i32data)
{
float floatctd=(float) i32data*Val_lsb/PGA; // U crête en mvolts
if (abs(floatctd)>=2047) {
floatctd=20*(log10(abs(floatctd)))-50; // P en dBm +30-20*log10(sqr(2))-10*log10(50)
str=(String(floatctd,1)+">>> ");
}
else if (abs(floatctd)<=0.002) {
floatctd=20*(log10(abs(floatctd)))-50; // P en dBm +30-20*log10(sqr(2))-10*log10(50)
str=(' '+String(floatctd,0)+"<<< ");
}
else {
floatctd=20*(log10(abs(floatctd)))-50; // P en dBm +30-20*log10(sqr(2))-10*log10(50)
if (floatctd>-50) {str=(String(floatctd,1)+"dBm ");}
else {str=(' '+String(floatctd,0)+"dBm ");}
}
return (str);
}*/
// * * * PGA_Auto // * * * * * * * * *
/* PGA=gain PEmV data g=1 data bascule pour g=1
1 2048 7F FF FF 1F FF FF -> 2
2 1024 3F FF FF 0F FF FF -> 4
4 512 1F FF FF 07 FF FF -> 8
8 256 0F FF FF 03 FF FF -> 16
16 128 07 FF FF 01 FF FF -> 32
32 64 03 FF FF 00 FF FF -> 64
64 32 01 FF FF 00 7F FF -> 128
128 16 00 FF FF 00 3F FF -> 128
*/
void PGA_Auto()
{
if (abs(adc_data) <= 0x3FFF) { // version gain 1 à 128 (pas pb mode commun)
pc_ads1220.set_pga_gain(PGA_GAIN_128);
PGA = 128;
GIndice = 7;
}
else if (abs(adc_data) <= 0x7FFF) {
pc_ads1220.set_pga_gain(PGA_GAIN_64);
PGA = 64;
GIndice = 6;
}
else if (abs(adc_data) <= 0xFFFF) {
pc_ads1220.set_pga_gain(PGA_GAIN_32);
PGA = 32;
GIndice = 5;
}
else if (abs(adc_data) <= 0x1FFFF) {
pc_ads1220.set_pga_gain(PGA_GAIN_16);
PGA = 16;
GIndice = 4;
}
else if (abs(adc_data) <= 0x03FFFF) {
pc_ads1220.set_pga_gain(PGA_GAIN_8);
PGA = 8;
GIndice = 3;
}
else if (abs(adc_data) <= 0x7FFFF) {
pc_ads1220.set_pga_gain(PGA_GAIN_4);
PGA = 4;
GIndice = 2;
}
else if (abs(adc_data) <= 0xFFFFF) {
pc_ads1220.set_pga_gain(PGA_GAIN_2);
PGA = 2;
GIndice = 1;
}
else {
pc_ads1220.set_pga_gain(PGA_GAIN_1);
PGA = 1;
GIndice = 0;
}
return;
}
// * * * Set_Gain // * * * * * * * * *
void Set_Gain(byte Gain)
{
switch (Gain) {
case 1:
pc_ads1220.set_pga_gain(PGA_GAIN_1);
PGA = 1;
GIndice = 0;
break;
case 2:
pc_ads1220.set_pga_gain(PGA_GAIN_2);
PGA = 2;
GIndice = 1;
break;
case 4:
pc_ads1220.set_pga_gain(PGA_GAIN_4);
PGA = 4;
GIndice = 2;
break;
case 8:
pc_ads1220.set_pga_gain(PGA_GAIN_8);
PGA = 8;
GIndice = 3;
break;
case 16:
pc_ads1220.set_pga_gain(PGA_GAIN_16);
PGA = 16;
GIndice = 4;
break;
case 32:
pc_ads1220.set_pga_gain(PGA_GAIN_32);
PGA = 32;
GIndice = 5;
break;
case 64:
pc_ads1220.set_pga_gain(PGA_GAIN_64);
PGA = 64;
GIndice = 6;
break;
case 128:
pc_ads1220.set_pga_gain(PGA_GAIN_128);
PGA = 128;
GIndice = 7;
break;
defaut:
pc_ads1220.set_pga_gain(PGA_GAIN_1);
PGA = 1;
}
}
void Calibration(void) // * * * * * * * * *
{
#if defined LCD
lcd.setCursor(0, 0);
lcd.print(F("Calibration du 0 "));
#endif
pc_ads1220.set_data_rate(Rate);
for (int i = 0; i <= 7; i++) {
sigma0 = 0;
for (int iad = 1; iad <= (nMoy * 4); iad++) {
Set_Gain((1 << i));
do {}
while ((digitalRead(ADS1220_DRDY_PIN)) == HIGH);
adc_data = pc_ads1220.Read_Data_Samples(); // mesure avec gain=GPA
sigma0 = sigma0 + adc_data;
}
sigma0 = sigma0 / (nMoy * 4);
OffsetG[i] = sigma0;
#if defined EEPROM_use
EEPROM.put(EadOffset + i * 4, sigma0);
#endif
#if defined LCD
if (i == 0) {
lcd.clear();
}
lcd.setCursor(0, 0);
lcd.print(F("Cal G="));
lcd.print(PGA);
lcd.print(F(" "));
lcd.print(sigma0);
lcd.print(F(" "));
lcd.setCursor(0, 1);
lcd.print(convertToString(sigma0));
#endif
#if Debug>=0
Serial.print(F("Cal G="));
Serial.print(PGA);
Serial.print(F(": "));
Serial.print(sigma0);
Serial.print(F(" "));
Serial.println(convertToString(sigma0));
#endif
delay(3000);
}
}
#if RTC_Present!=0
void getDateHeure(void) // * * * * * * * * *
{
DateTime now = rtc.now();
// cDateRTC[11] = now.toString(cDateRTC);
// cHeureRTC[9] = now.toString(cHeureRTC);
sprintf(cDateRTC, "%04d-%02d-%02d ", now.year(), now.month(), now.day());
sprintf(cHeureRTC, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
}
#endif
#if defined SD_Present
void OpenFile(void) // * * * * * * * * *
{
#if RTC_Present!=0
NomFichier[0] = cDateRTC[2];
NomFichier[1] = cDateRTC[3];
NomFichier[2] = cDateRTC[5];
NomFichier[3] = cDateRTC[6];
NomFichier[4] = cDateRTC[8];
NomFichier[5] = cDateRTC[9];
NomFichier[6] = '.';
NomFichier[7] = 't';
NomFichier[8] = 'x';
NomFichier[9] = 't';
NomFichier[10] = '\0';
#endif
// Supprimer le fichier s'il existe
// SD.remove(NomFichier);
// open the file. Note that only one file can be open at a time,
// so you have to close this one before opening another.
myFile = SD.open(NomFichier, FILE_WRITE);
#if RTC_Present!=0
MillisDebut = millis();
#endif
// if the file opened okay, write to it:
#if RTC_Present!=0
if (myFile) {
myFile.print(F("'"));
myFile.print(cDateRTC);
myFile.print(F(", "));
myFile.print(cHeureRTC);
myFile.print(F(", "));
myFile.println(MillisDebut);
#if defined ADS1220_Temp
myFile.println("'T=" + strTemp);
#endif
}
#endif
}
#endif
int freeRam () // * * * * * * * * *
{
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
#if defined ADS1220_Temp
void MesAffTemp(void) // Mesure et Affiche Température // * * * * * * * * *
{
// Mesure et affichage température du CAN
AValue = pc_ads1220.Read_SingleShot_Temperature_Wait();
strTemp = (String (float (AValue * 0.03125), 1) + "C ");
MillisTemp = millis();
#if defined LCD
lcd.setCursor(11, 3);
lcd.print(" " + strTemp);
#endif
#if Debug>=0
Serial.print(F("T= "));
Serial.print(bit24);
Serial.print(F(" "));
Serial.println(strTemp);
#endif
}
#endif
void PrintADS1220Config(void) // * * * * * * * * *
{
#if Debug>=0
Serial.print(pc_ads1220.readRegister_gt(0), HEX);
Serial.print(F(" "));
Serial.print(pc_ads1220.readRegister_gt(1), HEX);
Serial.print(F(" "));
Serial.print(pc_ads1220.readRegister_gt(2), HEX);
Serial.print(F(" "));
Serial.println(pc_ads1220.readRegister_gt(3), HEX);
#endif
}
// - - - ISR Timer2 // * * * * * * * * *
#if defined Timer2
ISR(TIMER2_OVF_vect) // Timer2 interrupt service routine
{
TCNT2 = timer2_counter; // preload timer
// digitalWrite(LED, !digitalRead(LED));
// digitalWrite(LED,1);
// PORTC |= 0x8;
#if defined MCP4821_P
DAC16 ++;
if (DAC16 >= 4095) {
DAC16 = 0;
}
// dacChip.writedata16(DAC16);
#endif
// PORTC &= ~0x8; // pulse = 126ns, période = 375ns
// digitalWrite(LED,0);
}
#endif
I am very aware that this code is very long, but if I delete something the problem goes away!
Herre now the modified library for the ADS1220 (I modified this library to be able to use the MCP4821 during an interruption).
//////////////////////////////////////////////////////////////////////////////////////////
//
// Arduino library for the ADS1220 24-bit ADC breakout board
//
// Author: Ashwin Whitchurch
// Copyright (c) 2018 ProtoCentral
//
// Based on original code from Texas Instruments
//
// This software is licensed under the MIT License(http://opensource.org/licenses/MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// For information on how to use, visit https://github.com/Protocentral/Protocentral_ADS1220/
//
// Modified 2021 by Jean-Paul Gendner (F5BU@orange.fr)
//
/////////////////////////////////////////////////////////////////////////////////////////
#include "Arduino.h"
#include "SPI.h"
//ADS1220 SPI commands
#define SPI_MASTER_DUMMY 0xFF
#define RESET 0x06 //Send the RESET command (06h) to make sure the ADS1220 is properly reset after power-up
#define START 0x08 //Send the START/SYNC command (08h) to start converting in continuous conversion mode
#define WREG 0x40
#define RREG 0x20
//Config registers
#define CONFIG_REG0_ADDRESS 0x00
#define CONFIG_REG1_ADDRESS 0x01
#define CONFIG_REG2_ADDRESS 0x02
#define CONFIG_REG3_ADDRESS 0x03
#define REG_CONFIG1_DR_MASK 0xE0
#define REG_CONFIG0_PGA_GAIN_MASK 0x0E
#define REG_CONFIG0_MUX_MASK 0xF0
#define DR_20SPS 0x00
#define DR_45SPS 0x20
#define DR_90SPS 0x40
#define DR_175SPS 0x60
#define DR_330SPS 0x80
#define DR_600SPS 0xA0
#define DR_1000SPS 0xC0
#define PGA_GAIN_1 0x00
#define PGA_GAIN_2 0x02
#define PGA_GAIN_4 0x04
#define PGA_GAIN_8 0x06
#define PGA_GAIN_16 0x08
#define PGA_GAIN_32 0x0A
#define PGA_GAIN_64 0x0C
#define PGA_GAIN_128 0x0E
#define MUX_AIN0_AIN1 0x00
#define MUX_AIN0_AIN2 0x10
#define MUX_AIN0_AIN3 0x20
#define MUX_AIN1_AIN2 0x30
#define MUX_AIN1_AIN3 0x40
#define MUX_AIN2_AIN3 0x50
#define MUX_AIN1_AIN0 0x60
#define MUX_AIN3_AIN2 0x70
#define MUX_AIN0_AVSS 0x80
#define MUX_AIN1_AVSS 0x90
#define MUX_AIN2_AVSS 0xA0
#define MUX_AIN3_AVSS 0xB0
#define MUX_SE_CH0 0x80
#define MUX_SE_CH1 0x90
#define MUX_SE_CH2 0xA0
#define MUX_SE_CH3 0xB0
#define _BVP(bit) (1<<(bit))
class Protocentral_ADS1220
{
private:
uint8_t m_config_reg0;
uint8_t m_config_reg1;
uint8_t m_config_reg2;
uint8_t m_config_reg3;
/* uint8_t Config_Reg0;
uint8_t Config_Reg1;
uint8_t Config_Reg2;
uint8_t Config_Reg3;
*/
uint8_t m_drdy_pin=6;
uint8_t m_cs_pin=7;
public:
uint8_t NewDataAvailable;
Protocentral_ADS1220();
void begin(uint8_t cs_pin, uint8_t drdy_pin);
void Start_Conv(void);
void ads1220_Reset(void);
void SPI_Command(unsigned char data_in);
void writeRegister(uint8_t address, uint8_t value);
uint8_t readRegister(uint8_t address);
uint8_t readRegister_gt(uint8_t address);
uint8_t * Read_Data(void);
int32_t Read_WaitForData();
void get_config_reg(void);
// void get_config_reg(uint8_t *array);
void PGA_OFF(void);
void PGA_ON(void);
void set_conv_mode_continuous(void);
void Single_shot_mode_ON(void);
void set_data_rate(int datarate);
void set_pga_gain(int pgagain);
void select_mux_channels(int channels_conf);
void set_conv_mode_single_shot(void);
void Start_SingleShot_SingleEnded(uint8_t channel_no);
int32_t Read_SingleShot_WaitForData(void);
int32_t Read_SingleShot_SingleEnded_WaitForData(uint8_t channel_no);
int16_t Read_SingleShot_Temperature_Wait(void);
int32_t Read_Data_Samples();
};
And
//////////////////////////////////////////////////////////////////////////////////////////
//
// Arduino library for the ADS1220 24-bit ADC breakout board
//
// Author: Ashwin Whitchurch
// Copyright (c) 2018 ProtoCentral
//
// Based on original code from Texas Instruments
//
// This software is licensed under the MIT License(http://opensource.org/licenses/MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// For information on how to use, visit https://github.com/Protocentral/Protocentral_ADS1220/
//
// Modified 2021 by Jean-Paul Gendner (F5BU@orange.fr)
//
/////////////////////////////////////////////////////////////////////////////////////////
#include <Arduino.h>
#include "Protocentral_ADS1220_g.h"
#include <SPI.h>
#if defined (SPI_HAS_TRANSACTION)
static SPISettings ADCSPISettings;
#endif
//#define BOARD_SENSYTHING ST_1_3
Protocentral_ADS1220::Protocentral_ADS1220() // Constructors
{}
void Protocentral_ADS1220::writeRegister(uint8_t address, uint8_t value)
{
digitalWrite(m_cs_pin,LOW);
SPI.transfer(WREG|(address<<2));
SPI.transfer(value);
digitalWrite(m_cs_pin,HIGH);
}
uint8_t Protocentral_ADS1220::readRegister(uint8_t address)
{
uint8_t data;
digitalWrite(m_cs_pin,LOW);
SPI.transfer(RREG|(address<<2));
data = SPI.transfer(SPI_MASTER_DUMMY);
digitalWrite(m_cs_pin,HIGH);
return data;
}
uint8_t Protocentral_ADS1220::readRegister_gt(uint8_t address)
{
uint8_t data;
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(ADCSPISettings);
#endif
digitalWrite(m_cs_pin,LOW);
SPI.transfer(RREG|(address<<2));
data = SPI.transfer(SPI_MASTER_DUMMY);
digitalWrite(m_cs_pin,HIGH);
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
return data;
}
void Protocentral_ADS1220::SPI_Command(unsigned char data_in)
{
digitalWrite(m_cs_pin, LOW);
SPI.transfer(data_in);
digitalWrite(m_cs_pin, HIGH);
}
void Protocentral_ADS1220::begin(uint8_t cs_pin, uint8_t drdy_pin)
{
#if defined (SPI_HAS_TRANSACTION)
ADCSPISettings = SPISettings(6500000, MSBFIRST, SPI_MODE1); // min période de 150ns
SPI.beginTransaction(ADCSPISettings);
#endif
m_drdy_pin=drdy_pin;
m_cs_pin=cs_pin;
pinMode(m_cs_pin, OUTPUT);
pinMode(m_drdy_pin, INPUT);
#if defined(BOARD_SENSYTHING)
SPI.begin(18, 35, 23, 19);
#else
SPI.begin();
#endif
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE1);
ads1220_Reset();
// digitalWrite(m_cs_pin,LOW);
m_config_reg0 = 0x00; //Default settings: AINP=AIN0, AINN=AIN1, Gain 1, PGA enabled
// m_config_reg0 = 0x01; //Default settings: AINP=AIN0, AINN=AIN1, Gain 1, PGA dissabled
m_config_reg1 = 0x04; //Default settings: DR=20 SPS, Mode=Normal, Conv mode=continuous, Temp Sensor disabled, Current Source off
m_config_reg2 = 0x10; //Default settings: Vref internal, 50/60Hz rejection, power open, IDAC off
m_config_reg3 = 0x00; //Default settings: IDAC1 disabled, IDAC2 disabled, DRDY pin only
writeRegister( CONFIG_REG0_ADDRESS , m_config_reg0);
writeRegister( CONFIG_REG1_ADDRESS , m_config_reg1);
writeRegister( CONFIG_REG2_ADDRESS , m_config_reg2);
writeRegister( CONFIG_REG3_ADDRESS , m_config_reg3);
/* Serial.print("m_Config: ");
Serial.print(m_config_reg0,HEX);
Serial.print(" ");
Serial.print(m_config_reg1,HEX);
Serial.print(" ");
Serial.print(m_config_reg2,HEX);
Serial.print(" ");
Serial.println(m_config_reg3,HEX);
Serial.println(" ");
Config_Reg0 = readRegister(CONFIG_REG0_ADDRESS);
Config_Reg1 = readRegister(CONFIG_REG1_ADDRESS);
Config_Reg2 = readRegister(CONFIG_REG2_ADDRESS);
Config_Reg3 = readRegister(CONFIG_REG3_ADDRESS);
Serial.print("Config_Reg : ");
Serial.print(Config_Reg0,HEX);
Serial.print(" ");
Serial.print(Config_Reg1,HEX);
Serial.print(" ");
Serial.print(Config_Reg2,HEX);
Serial.print(" ");
Serial.println(Config_Reg3,HEX);
Serial.println(" ");
*/
// digitalWrite(m_cs_pin,HIGH);
//Start_Conv();
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
void Protocentral_ADS1220::ads1220_Reset()
{
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(ADCSPISettings);
#endif
SPI_Command(RESET);
delayMicroseconds(100);
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
void Protocentral_ADS1220::Start_Conv()
{
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(ADCSPISettings);
#endif
SPI_Command(START);
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
void Protocentral_ADS1220::PGA_ON(void)
{
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(ADCSPISettings);
#endif
m_config_reg0 &= ~_BVP(0);
writeRegister(CONFIG_REG0_ADDRESS,m_config_reg0);
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
void Protocentral_ADS1220::PGA_OFF(void)
{
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(ADCSPISettings);
#endif
m_config_reg0 |= _BVP(0);
writeRegister(CONFIG_REG0_ADDRESS,m_config_reg0);
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
void Protocentral_ADS1220::set_conv_mode_continuous(void)
{
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(ADCSPISettings);
#endif
m_config_reg1 |= _BVP(2);
writeRegister(CONFIG_REG1_ADDRESS,m_config_reg1);
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
void Protocentral_ADS1220::set_conv_mode_single_shot(void)
{
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(ADCSPISettings);
#endif
m_config_reg1 &= ~_BVP(2);
writeRegister(CONFIG_REG1_ADDRESS,m_config_reg1);
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
void Protocentral_ADS1220::set_data_rate(int datarate)
{
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(ADCSPISettings);
#endif
m_config_reg1 &= ~REG_CONFIG1_DR_MASK;
m_config_reg1 |= datarate;
writeRegister(CONFIG_REG1_ADDRESS,m_config_reg1);
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
void Protocentral_ADS1220::select_mux_channels(int channels_conf)
{
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(ADCSPISettings);
#endif
m_config_reg0 &= ~REG_CONFIG0_MUX_MASK;
m_config_reg0 |= channels_conf;
writeRegister(CONFIG_REG0_ADDRESS,m_config_reg0);
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
void Protocentral_ADS1220::set_pga_gain(int pgagain)
{
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(ADCSPISettings);
#endif
m_config_reg0 &= ~REG_CONFIG0_PGA_GAIN_MASK;
m_config_reg0 |= pgagain ;
writeRegister(CONFIG_REG0_ADDRESS,m_config_reg0);
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
void Protocentral_ADS1220::get_config_reg()
//void Protocentral_ADS1220::get_config_reg(uint8_t *array)
{
static uint8_t config_Buff[4];
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(ADCSPISettings);
#endif
/* m_config_reg0 = readRegister(CONFIG_REG0_ADDRESS);
m_config_reg1 = readRegister(CONFIG_REG1_ADDRESS);
m_config_reg2 = readRegister(CONFIG_REG2_ADDRESS);
m_config_reg3 = readRegister(CONFIG_REG3_ADDRESS);*/
config_Buff[0] = readRegister(CONFIG_REG0_ADDRESS);
config_Buff[1] = readRegister(CONFIG_REG1_ADDRESS);
config_Buff[2] = readRegister(CONFIG_REG2_ADDRESS);
config_Buff[3] = readRegister(CONFIG_REG3_ADDRESS);
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
/* config_Buff[0] = m_config_reg0 ;
config_Buff[1] = m_config_reg1 ;
config_Buff[2] = m_config_reg2 ;
config_Buff[3] = m_config_reg3 ;
array[0] = m_config_reg0 ;
array[1] = m_config_reg1 ;
array[2] = m_config_reg2 ;
array[3] = m_config_reg3 ;*/
// return config_Buff;
return;
}
void Protocentral_ADS1220::Start_SingleShot_SingleEnded(uint8_t channel_no)
{
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(ADCSPISettings);
#endif
// select_mux_channels(channel_no);
m_config_reg0 &= ~REG_CONFIG0_MUX_MASK;
m_config_reg0 |= channel_no;
writeRegister(CONFIG_REG0_ADDRESS,m_config_reg0);
// delayMicroseconds(10);
SPI_Command(START);
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
int32_t Protocentral_ADS1220::Read_WaitForData()
{
static byte SPI_Buff[3];
long int bit24;
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(ADCSPISettings);
#endif
do {}
while ((digitalRead(m_drdy_pin)) == HIGH); // Wait for DRDY to transition low
{
digitalWrite(m_cs_pin,LOW); //Take CS low
for (int i = 0; i < 3; i++)
{
SPI_Buff[i] = SPI.transfer(SPI_MASTER_DUMMY);
}
digitalWrite(m_cs_pin,HIGH); // Clear CS to high
bit24 = SPI_Buff[0];
bit24 = (bit24 << 8) | SPI_Buff[1];
bit24 = (bit24 << 8) | SPI_Buff[2]; // Converting 3 bytes to a 24 bit int
bit24 = (bit24 << 8);
bit24 = (bit24 >> 8); // Converting 24 bit two's complement to 32 bit two's complement
}
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
return bit24;
}
int32_t Protocentral_ADS1220::Read_Data_Samples()
{
static byte SPI_Buff[3];
long int bit24;
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(ADCSPISettings);
#endif
digitalWrite(m_cs_pin,LOW); //Take CS low
for (int i = 0; i < 3; i++)
{
SPI_Buff[i] = SPI.transfer(SPI_MASTER_DUMMY);
}
digitalWrite(m_cs_pin,HIGH); // Clear CS to high
bit24 = SPI_Buff[0];
bit24 = (bit24 << 8) | SPI_Buff[1];
bit24 = (bit24 << 8) | SPI_Buff[2]; // Converting 3 bytes to a 24 bit int
bit24 = (bit24 << 8);
bit24 = (bit24 >> 8); // Converting 24 bit two's complement to 32 bit two's complement
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
return bit24;
}
int32_t Protocentral_ADS1220::Read_SingleShot_WaitForData(void)
{
static byte SPI_Buff[3];
long int bit24;
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(ADCSPISettings);
#endif
SPI_Command(START);
do {}
while ((digitalRead(m_drdy_pin)) == HIGH); // Wait for DRDY to transition low
{
digitalWrite(m_cs_pin,LOW); //Take CS low
for (int i = 0; i < 3; i++)
{
SPI_Buff[i] = SPI.transfer(SPI_MASTER_DUMMY);
}
digitalWrite(m_cs_pin,HIGH); // Clear CS to high
bit24 = SPI_Buff[0];
bit24 = (bit24 << 8) | SPI_Buff[1];
bit24 = (bit24 << 8) | SPI_Buff[2]; // Converting 3 bytes to a 24 bit int
bit24 = (bit24 << 8);
bit24 = (bit24 >> 8); // Converting 24 bit two's complement to 32 bit two's complement
}
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
return bit24;
}
int32_t Protocentral_ADS1220::Read_SingleShot_SingleEnded_WaitForData(uint8_t channel_no)
{
static byte SPI_Buff[3];
long int bit24;
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(ADCSPISettings);
#endif
// select_mux_channels(channel_no);
m_config_reg0 &= ~REG_CONFIG0_MUX_MASK;
m_config_reg0 |= channel_no;
writeRegister(CONFIG_REG0_ADDRESS,m_config_reg0);
// delayMicroseconds(10);
SPI_Command(START);
do {}
while ((digitalRead(m_drdy_pin)) == HIGH); // Wait for DRDY to transition low
{
digitalWrite(m_cs_pin,LOW); //Take CS low
for (int i = 0; i < 3; i++)
{
SPI_Buff[i] = SPI.transfer(SPI_MASTER_DUMMY);
}
digitalWrite(m_cs_pin,HIGH); // Clear CS to high
bit24 = SPI_Buff[0];
bit24 = (bit24 << 8) | SPI_Buff[1];
bit24 = (bit24 << 8) | SPI_Buff[2]; // Converting 3 bytes to a 24 bit int
bit24 = (bit24 << 8);
bit24 = (bit24 >> 8); // Converting 24 bit two's complement to 32 bit two's complement
}
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
return bit24;
}
int16_t Protocentral_ADS1220::Read_SingleShot_Temperature_Wait(void)
{
static byte SPI_Buff[3];
int16_t bit16=0;
#if defined (SPI_HAS_TRANSACTION)
SPI.beginTransaction(ADCSPISettings);
#endif
// SPI_Command(RESET);
// m_config_reg1 |= 0x02; // T
writeRegister(CONFIG_REG1_ADDRESS , 0xC6);
SPI_Command(START);
do {}
while ((digitalRead(m_drdy_pin)) == HIGH); // Wait for DRDY to transition low
digitalWrite(m_cs_pin,LOW); //Take CS low
delayMicroseconds(1);
//SPI_Command(0x10);
for (int i = 0; i < 2; i++)
{
SPI_Buff[i] = SPI.transfer(SPI_MASTER_DUMMY);
}
delayMicroseconds(1);
digitalWrite(m_cs_pin,HIGH); // Clear CS to high
bit16 = SPI_Buff[0];
bit16 = (bit16 << 8) | SPI_Buff[1];
bit16 = (bit16 >> 2); // 14 bits signés température
// m_config_reg1 &= ~0x02;
writeRegister(CONFIG_REG1_ADDRESS , m_config_reg1);
#if defined (SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
return bit16;
}
I do not put the MCP4821 modified library because the MCP4821 is initialized but not used in the loop.
I'm stunned that adding a nop statement could have such an effect. It is no longer programming but alchemy! I compared the resulting assembly codes and found that there were huge differences and nowhere found the nop lines.
Any help will be welcome.
Regards