Измерения на ADS 1115a

Вставь принт пробела между выводом значений.

Спойлер
if(millis() - last_millis >= 1000)
	{
  last_millis = millis();		
  Serial.print("COMP:\t  ");
  Serial.print(val_01);
	Serial.print("  ");
	Serial.print(Index);
	Serial.print("  ");
  Serial.println((float)(timer1-timer0));
    }   

@mihail14 , для интервалов, измеряемых мсекундами или десятками мс, нужно использовать функцию micros() , а не миллис().
Прошли 40 мс, считываем значение по и2с, затем в оставшееся время делаем другие дела, но так чтоб суммарное время было не более скажем 38 мс. Если не укладываемся в это время, то нужно или интервал опроса увеличить, или задачи делить на части. Например, дисплей 2004 не весь обновлять, а по одной строке. Или нужно в сериал на скорости 9600 бод строку в сотню байт отправить, чтоб не было тормозов, нужно сначала 64 байта отправить, а через 40 мс остальные 36 байт.

На Arduino AVR интервалы изначально неточные: чередуются приращения на одну и на две единицы так, чтобы за секунду набиралось общее приращение на 1000 единиц.

Или даже по одному символу, как, например, здесь:

Оказывается, можно было обойтись без переменной value_.
Вместо:

ISR(TIMER1_COMPA_vect)
{
  sei();
  value_ = ADS.readADC_Differential_0_3();
  reading_is_allowed = true;  
 }

Записать:

ISR(TIMER1_COMPA_vect)
{
  sei();
  (volatile) ADS.readADC_Differential_0_3();
  reading_is_allowed = true;  
 }

Правда, это работает только в новой версии IDE (1.8.57.0). В старой версии IDE (1.6.7) это почему-то не работает.

Ещё раз всем огромное спасибо. Особенно участнику с ником [Дим-мычъ].

Подскажите, пожалуйста, как мне теперь замерить время между прерываниями, т.е. убедиться, что они происходят через 40 мс. Вставил строку измерения в обработчик прерывания после sei():

/***************************************************************************************************
   ПОДКЛЮЧЕНИЕ БИБЛИОТЕК
****************************************************************************************************/
#include <ADS1X15.h>    // Подключаем библиотеку by Rob Tillaart

/***************************************************************************************************
  МАКРООПРЕДЕЛЕНИЯ
****************************************************************************************************/
#define array_size 2   // Размер массива для скользящего среднего
#define false 0
#define true 1
/***************************************************************************************************
  АДРЕС АЦП ADS1115
****************************************************************************************************/
ADS1115 ADS(0x48); // Вывод ADDR ADS1115 подключен к GND
// ADS1115 ADS(0x49); // Вывод ADDR ADS1115 подключен к VDD
// ADS1115 ADS(0x4A); // Вывод ADDR ADS1115 подключен к SDA
// ADS1115 ADS(0x4B); // Вывод ADDR ADS1115 подключен к SCL

/***************************************************************************************************
  ОБЪЯВЛЕНИЕ ГЛОБАЛЬНЫХ ПЕРЕМЕННЫХ
****************************************************************************************************/
float voltage_ADS [array_size];     // Объявляем массив напряжений для скользящего среднего
float voltage_average;              // Усредненное значение напряжения в мкВ
int code[array_size];               // Объявляем массив результатов преобразования АЦП (коды)
bool array_is_full = false;         // флаг заполнения массива
// array_is_full = false - массив не заполнен
// array_is_full = true - массив заполнен
volatile bool reading_is_allowed = false;    // флаг разрешения чтения результата преобразования
// reading_is_allowed = false - чтение запрещено
// reading_is_allowed = true - чтение разрешено
unsigned char Index = 0;            // Индекс элементов массива. Первоначальное значение = 0
unsigned long timer0 = 0;
unsigned long timer1;

float val_01 = 0;
volatile unsigned int value_ = 0;
volatile bool ADCflg = false;

/***************************************************************************************************
  ФУНКЦИЯ SETUP
****************************************************************************************************/
void setup(void)
{
  /******************************************************************************************/
  /* Инициируем последовательное соединение Ардуино с ПК
    и задаём скорость передачи данных в бит/c (бод) */
  Serial.begin(115200);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);
  delay(100);

  Wire.begin();
  // Wire.setClock(100000);

  /***************************************************************************************************
    НАСТРОЙКА АЦП ADS1115
  ****************************************************************************************************/
  /* Настраиваем параметры АЦП ADS1115 */

  /* Инициализируем микросхему ADS1115 и задаём её параметры конфигурации по умолчанию */
  ADS.begin();

  /* Задаём к-т усиления */
  //ADS.setGain(16);  //к-т усиления 16, максимальное напряжение ±0.256V, 1 бит = 0.0078125mV
  // ADS.setGain(8);    //к-т усиления 8, максимальное напряжение ±0.512V, 1 бит = 0.015625mV
  // ADS.setGain(4);    //к-т усиления 4, максимальное напряжение ±1.024V, 1 бит = 0.03125mV
  // ADS.setGain(2);    //к-т усиления 2, максимальное напряжение ±2.048V, 1 бит = 0.0625mV
  ADS.setGain(1);    //к-т усиления 1, максимальное напряжение ±4.096V, 1 бит = 0.125mV
  // ADS.setGain(0);    //к-т усиления 2/3, максимальное напряжение ±6.144V, 1 бит = 0.1875mV (DEFAULT)

  /* Задаём скорость преобразования */
  // ADS.setDataRate(7);  //скорость преобразования максимум 860SPS (Самая быстрая)
  // ADS.setDataRate(6);  //скорость преобразования максимум 475SPS
  // ADS.setDataRate(5);  //скорость преобразования максимум 250SPS
  ADS.setDataRate(4);  //скорость преобразования максимум 128SPS (DEFAULT)
  // ADS.setDataRate(3);  //скорость преобразования максимум 64SPS
  // ADS.setDataRate(2);  //скорость преобразования максимум 32SPS
  // ADS.setDataRate(1);  //скорость преобразования максимум 16SPS
  // ADS.setDataRate(0);  //скорость преобразования максимум 8SPS   (Самая медленная)

  /* Задаём режим преобразования */
  // ADS.setMode(0);  //непрерывный режим
  ADS.setMode(1);  //однократный режим

  ADS.requestADC_Differential_0_3();

  /***************************************************************************************************
    НАСТРОЙКА ТАЙМЕРА
  ****************************************************************************************************/
  /* Настраиваем Таймер1 на прерывание по совпадению A.
    Таймер1 будет вызывать прерывание каждые 40 мс (частота 25 Гц).
    Он-лайн калькулятор: http://rcl-radio.ru/?p=111487&ysclid=m0oc5vjb9o687744588 */

  cli();
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  // (16000000/((624+1)x1024))=25 Hz
  OCR1A = 624;
  TCCR1B |= (1 << WGM12);
  // Prescaler 1024
  TCCR1B |= (1 << CS12) | (1 << CS10);
  TIMSK1 |= (1 << OCIE1A);
  sei();

}

/***************************************************************************************************
  ФУНКЦИЯ LOOP
****************************************************************************************************/
void loop(void)
{
  static unsigned long last_millis = 0;

  if (ADS.isReady() && ADCflg)
  {
    // val_01 = (ADS.toVoltage(ADS.getValue()))*1000000;
    val_01 = ADS.toVoltage(value_ ) * 1000000 ; //
    //timer0 = micros();
    //ADS.requestADC_Differential_0_3();//не будет работать - раскомментировать эту строчку
    //timer1 = micros();
    ADCflg = false;
	Serial.println((float)(timer0));
if(millis() - last_millis >= 1000)
	{
  last_millis = millis();		
  Serial.print("COMP:\t  ");
  Serial.print(val_01);
	Serial.print("  ");
	Serial.print(Index);
	Serial.print("  ");
  //Serial.println((float)(timer1-timer0));
    }
  }
  //delay (1000);
}

ISR(TIMER1_COMPA_vect)
{
  sei();
  timer0 = millis() - timer0;  
  value_ = ADS.readADC_Differential_0_3();
  ADCflg = true;
  //timer1 = millis();                   // останавливаем  отсчет времени
  //Serial.println((float)(timer1));
  //ADS.requestADC_Differential_0_1();     // запуск преобразования для дифференциального чтения между входами 0 и 1 АЦП
  //ADS.requestADC_Differential_0_3();     // запуск преобразования для дифференциального чтения между входами 0 и 3 АЦП
  //ADS.requestADC_Differential_1_3();     // запуск преобразования для дифференциального чтения между входами 1 и 3 АЦП
  //ADS.requestADC_Differential_2_3();     // запуск преобразования для дифференциального чтения между входами 2 и 3 АЦП
  //timer0 = timer1;
  //reading_is_allowed = true;            // выставляем флаг "чтение результата преобразования разрешено"
  //TCNT1 = 0;          // Обнуляем счетный регистр TCNT1 таймера/счетчика T1
  Index++;
}

Выводится какая-то ерунда.

Попробуйте так

Спойлер
void loop(void)
{
  static unsigned long last_millis = 0;
  static unsigned long micros_save[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  static byte cycle = 0;
  
  if (ADS.isReady() && ADCflg)
  {
	if(cycle < 10)		
	micros_save[cycle++] = micros();
    // val_01 = (ADS.toVoltage(ADS.getValue()))*1000000;
    val_01 = ADS.toVoltage(value_ ) * 1000000 ; //
    //timer0 = micros();
    //ADS.requestADC_Differential_0_3();//не будет работать - раскомментировать эту строчку
    //timer1 = micros();
    ADCflg = false;
	Serial.println((float)(timer0));
if(millis() - last_millis >= 1000)
	{
  last_millis = millis();		
  Serial.print("COMP:\t  ");
  Serial.print(val_01);
	Serial.print("  ");
	Serial.print(Index);
	Serial.print("  ");
	for(byte i = 0; i < 10; i++)
	 Serial.println(micros_save[i]);	
	
  //Serial.println((float)(timer1-timer0));
    }
  }
  //delay (1000);
}

Результат:

А так

Спойлер
void loop(void)
{
  static unsigned long last_millis = 0;
  static unsigned long micros_save[4] = {0, 0, 0, 0};
  static byte cycle = 0;
  
  if (ADS.isReady() && ADCflg)
  {
	if(cycle < 4)		
	micros_save[cycle++] = micros();
    // val_01 = (ADS.toVoltage(ADS.getValue()))*1000000;
    val_01 = ADS.toVoltage(value_ ) * 1000000 ; //
    //timer0 = micros();
    //ADS.requestADC_Differential_0_3();//не будет работать - раскомментировать эту строчку
    //timer1 = micros();
    ADCflg = false;
	Serial.println((float)(timer0));
if(millis() - last_millis >= 1000)
	{
  last_millis = millis();		
  Serial.print("COMP:\t  ");
  Serial.print(val_01);
	Serial.print("  ");
	Serial.print(Index);
	Serial.print("  ");
	for(byte i = 0; i < 4; i++)
	 Serial.println(micros_save[i]);	
  //Serial.println((float)(timer1-timer0));
    }
  }
  //delay (1000);
}

Результат:

Закомментировал строку
Serial.println((float)(timer0));
Результат:

Всё получилось в такой версии:

ISR(TIMER1_COMPA_vect)
{
  sei();
    static unsigned long prev_time = 0;
    
    unsigned long _time = micros();
    unsigned long _period = _time - prev_time;
    prev_time = _time;
        
    Serial.println(_period, DEC);
  //timer0 = millis() - timer0;                   
  value_ = ADS.readADC_Differential_0_3();
  array_is_full = true;
  reading_is_allowed = true;
  //Serial.println((float)(timer1));
  //ADS.requestADC_Differential_0_1();     // запуск преобразования для дифференциального чтения между входами 0 и 1 АЦП
  //ADS.requestADC_Differential_0_3();     // запуск преобразования для дифференциального чтения между входами 0 и 3 АЦП
  //ADS.requestADC_Differential_1_3();     // запуск преобразования для дифференциального чтения между входами 1 и 3 АЦП
  //ADS.requestADC_Differential_2_3();     // запуск преобразования для дифференциального чтения между входами 2 и 3 АЦП
  //timer0 = timer1;
  //reading_is_allowed = true;            // выставляем флаг "чтение результата преобразования разрешено"
  //TCNT1 = 0;          // Обнуляем счетный регистр TCNT1 таймера/счетчика T1
  Index++;
 }

Так в моём примере она и так закоментирована.
Результат правильный, вывод подправил
4-ре замера подряд. Разницу видно.

Спойлер
void loop(void)
{
  static unsigned long last_millis = 0;
  static unsigned long micros_save[4] = {0, 0, 0, 0};
  static byte cycle = 0;
  
  if (ADS.isReady() && ADCflg)
  {
	if(cycle < 4)		
	micros_save[cycle++] = micros();
    // val_01 = (ADS.toVoltage(ADS.getValue()))*1000000;
    val_01 = ADS.toVoltage(value_ ) * 1000000 ; //
    //timer0 = micros();
    //ADS.requestADC_Differential_0_3();//не будет работать - раскомментировать эту строчку
    //timer1 = micros();
    ADCflg = false;
	//Serial.println((float)(timer0));
if(millis() - last_millis >= 1000)
	{
  last_millis = millis();		
  Serial.print("COMP:\t  ");
  Serial.print(val_01);
  Serial.println();
	for(byte i = 0; i < 4; i++)
	 Serial.println(micros_save[i]);	
  //Serial.println((float)(timer1-timer0));
    }
  }
  //delay (1000);
}

P.S. Подправил

Понимаю, что совать всё подряд в обработчик прерывания не следует, но, думаю, что для проверки можно.

Ну да, их там две ))

ОК. Спасибо за помощь.

интересно, с какой целью таймер приводится к типу флоат перед печатью.

Думаю, просто для единообразия

Единообразия с чем?