Для макетирования была выбрана ардуинка UNO. Отработана программа перебора адресов мультиплексора. При отработки программы обработки данных возникла проблема. Для её решения был отключен мультиплексор, а аналоговый вход А0 закорочен на землю. Далее привожу листинг программы.
uint8_t kol = 16; // количество лучей;
uint8_t iter = 30; // Число раз считывания с аналогового порта
uint8_t alarm = 0; // Флаг тревоги.
uint16_t reference[16] = {0}; // Массив данных по лучам
uint16_t average = 0; // Среднее значение считанного
// -------------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
pinMode(13, OUTPUT); // Индикатор работы
uint16_t average = 0; // Среднее значение данных по лучу
// Калибровка данных по kol лучам
for (uint8_t i = 0; i < kol; i++)// Цикл по лучам
{
// функциzя установки адреса луча !!! Здесь пропущена
average = readRey(); // Чтение аналогового порта iter раз
reference[i] = average; // Запись среднего в массив по лучу.
}
digitalWrite(13, ! digitalRead(13)); // Мигаем для контроля
}
// -------------------------------------------------------------------------------------
void loop() {
// Основная работа после калибровки.
for (uint8_t i = 0; i < kol; i++) // Цикл по лучам kol раз
{
// функциzя установки адреса луча !!! Здесь пропущена
average = readRey(); // на функцию чтение аналогового порта iter раз
alarm = reference[i] - average; // разница между калибровкой и считанным
// Для отладки вывод сравнения из массива и считанного
Serial.print(i); Serial.print(":"); Serial.print(reference[i]); Serial.print("-");
Serial.print(average); Serial.print(" = "); Serial.println(alarm);
// Функция обработки сигнала тревоги !!! Здесь нет
}
digitalWrite(13, ! digitalRead(13)); // Мигаем для контроля
Serial.println(); // Для отладки
}// конец loop()
// ======================================================================================
uint16_t readRey() // Чтение и усреднение данных по лучу
// Используется глобальная переменная iter
// Возврат среднее значенияе
{
uint16_t dat = 0;
for (uint8_t i = 0; i < iter; i++)
{
delay(5); // для устранения переходных процессов
dat = dat + analogRead(0); //Чтение с 0 аналоговога порта
}
dat = dat / iter;
return dat; // вернули среднее значение считанного
}
Идея отладки такова, читаем данные с А0 перед этим якобы устанавливаем адрес на мультиплексоре. Вычисляем среднее арифметическое и записываем в массив данных. После калибровки пнреходим на основную работу. Устанавливаем адрес, читаем и усредняем данные, сравниваем с данными в массиве и при разнице идём на обработку ошибки.
В чём проблема! При сравнении “‘эталона“ из массива и считанного сейчас большая разница. Причём это при закороченной А0 на землю. Ещё непонятка. Разница уменьшается от нулевого адреса к старшему.
Написал функцию проверки содержимого массива reference[16]. Вставил вызов функции в разделе setup() до цикла калибровки данных по лучам. Привожу результат:
В этом-то и смысл проверки чтения. Перебор адресов я отработал, там всё в прядке. Проверял и осциллографом и светодиодиками и многоканальнам анализатором. В данном скетче его не привожу, дабы не отвлекать на него внимания. В коментариях есть ссылка на место вызова функции установки очередного азреса.
Этот ряд чисел должен совпадать с первыми числами на каждой строке на этой выдаче:
А на деле - огромная разница.
Из этого следует, что ваш массив reference где-то между setup() и loop() портится. Поскольку в приведенном Вами коде ничего похожего нет, я делаю единственный возможный вывод - вы выложили на форум не тот код, который используете сами. Собственно, вы и сами об этом пишете:
Пожалуйста, покажите полный код. Ну или не показывайте - но тогда помощи не ждите.
uint8_t kol = 16; // количество лучей;
uint8_t iter = 30; // Количества итераций считывания с аналогового порта
uint8_t koef = 100; // Коэффициент расхождения дельта ошибки.
uint8_t alarm = 0; // Флаг тревоги.
uint16_t reference[16] = {0}; // Массив данных по лучам
uint8_t malarm[16] = {0}; // Массив данных тревог.
uint16_t average = 0; // Среднее значение
#include "CyberLib.h"
// -------------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
pinMode(13, OUTPUT); // Индикатор работы
DDRD = DDRD | B00111100; // инициализация пинов 2,3,4,5 на выход
//unsigned int
uint16_t average = 0; // Среднее значение данных по лучу
readReference ();// Для отладки проверка массива перед его заполнением.
for (uint8_t i = 0; i < kol; i++)// Цикл по лучам
{
nambRey(i); // На функцию установки адреса луча
for(uint8_t j = 0; j < 3; j++)
{
average = readRey(); // Чтение аналогового порта iter раз
reference[i] = average; // Запись среднего в массив по лучу.
}
average = 0;
}
digitalWrite(13, ! digitalRead(13)); // Мигаем для контроля
// readReference (); // Контрольное чтение массива дпнных по лучам. Отладка
}
// -------------------------------------------------------------------------------------
void loop() {
// Основная работа после инициализации.
for(uint8_t i = 0; i < kol; i++)// Цикл по лучам
{
nambRey(i); // На функцию установки адреса луча
average = readRey(); // Чтение аналогового порта iter раз
alarm = reference[i] - average;
// alarm = abs(alarm); // Получили сигнал тревоги
// if (alarm > koef) {mAlarm(i);} // На обработку тревоги
Serial.print(i); Serial.print(":"); Serial.print(reference[i]);Serial.print("-");Serial.print(average);Serial.print(" = "); Serial.println(alarm);
}
digitalWrite(13, ! digitalRead(13)); // Мигаем для контроля
// delay(9000);
Serial.println();
}//Loop()
// ======================================================================================
void nambRey(uint8_t n) // Расчет и установка луча опроса
{
/* Цикл для перебора адресов используя 2,3,4,5 ноги
* Значения 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60
* На входе n номер луча
*/
int k;
n = n * 4; // Расчет следующего адреса
// Serial.print("лучь = ");Serial.print(n);Serial.print(" "); // Отладка
PORTD &= B11000011; // Обнуляем рабочие пины
PORTD |= n; // Выставляем значение адреса на выход
}
//------------------------------------------------------------------
uint16_t readRey() // Чтение и усреднение данных по лучу
// Используется глобальная переменная iter
// Возврат среднего значения
{
uint16_t dat = 0;
for(uint8_t i = 0; i < iter; i++)
{
delay(10);
dat = dat + A0_Read;
}
dat = dat / iter;
return dat;
}
// ------------------------------------------------------------------
void mAlarm(uint8_t n) // Массив сигналов тревоги
/* Накопление сигналов тревоги по лучам
* на входе имеем номер тревожного луча
* Если количество тревог > максимума по лучу,
* то данные количества тревог по лучу обнуляется
*/
{
malarm[n] = malarm[n] + 1; // Изменили количество тревог по лучу
for(uint8_t i = 0; i < kol; i++)
{
if (malarm[i] > 5) {malarm[i] = 0;} // Сбросили максимум тревог
// Serial.print(i); Serial.print("-");Serial.println(malarm[i]);
}
}
// ============= Для отладки. ==================
//-----------Чтение массива reference.-----------
void readReference ()
{
Serial.println( "Массив");
for (uint8_t i = 0; i < kol; i++)
{
Serial.print(i);
Serial.print(" = ");
Serial.print(reference[i]);
Serial.println(", ");
}
Serial.println();
}
Не поверите - просто убрал перемычку, замыкающую A0 на GND.
В принципе, глядя на ваш листинг из самого первого сообщения:
у меня сразу была такая мысль. Потому что самое простое и логичное обьяснение такому поведению - никуда не подключенный аналоговый вход, который ловит все окружающие наводки. Но я поверил Вам, когда вы написали, что притянули А0 к земле.
После запуска теста все стало очевидно.
Я не знаю, вводили ли вы нас в заблуждение или это получилось случайно… но аналоговый вход А0 в ваших тестах не заземлен. Может перепутали вход… или непропай на плате… или перемычка с пина соскочила…
В общем, ищите проблемы с железом. Код здесь не при чем.
Если честно я в шоке. До установки перемычки на землю у меня был ещё больший разброс донных. Перемычку поставил именно из за подозрения, что свободный вход насосёт помех выше крыши. Спасибо за помощь. Проверю отпишусь.
Пусть с большим опазданием, но отвечаю. Огромное сасибо за помощ. Тщательно проверил контакт перемычки. Оказалось на ней был лак и хорошего контакта не было. Подтвердились слова о том, что радиотехника это наука о контактах. Контакт есть, где его не должно быть и его нет, где он должен быть.