Может кому пригодится, а может кто и оптимизацию предложит по уменьшению времени выполнения кода, т.к. из-за этого возникает погрешность в несколько градусов. Не критично для такого приборчика, но она есть. В идеале, конечно, лучше сделать компаратор на операционном усилителе. Код от чайника: Код (C++): void setup(){ //Serial.begin (9600); pinMode(7, OUTPUT); } void loop(){ int u1 = analogRead(A1); int u2 = analogRead(A2); //Serial.println (u1); //Serial.println (u2); if (u1 > u2){ digitalWrite(7, HIGH); }else if(u2 > u1) digitalWrite(7, LOW); }
Штатные функции digitalWrite и особенно analogRead очень медленные - это особенность совместимости с любой платой Arduino. Если с конкретной платой уже определились, гораздо быстрее читать/писать эти порты напрямую: https://habr.com/post/141442/ https://forum.arduino.ua/viewtopic.php?id=1071 http://codius.ru/articles/Тюнинг_Arduino_или_ускоряем_работу_платы http://codius.ru/articles/Arduino_у...ого_цифровой_преобразователь_АЦП_и_analogRead
Т.е. сделав вот так, мы сразу экономим почти 1,8 мс только на digitalWrite для 7-го пина? Код (C++): void setup(){ DDRD = DDRD | B11111100; // устанавливает выходы от 2 до 7 в качестве выходов } void loop(){ int u1 = analogRead(A1); int u2 = analogRead(A2); if (u1 > u2){ PORTD = B10000000; // sets digital pins 7 HIGH }else if(u2 > u1) PORTD = B00000000; // sets digital pins 7 LOW }
Аналогрид влёгкую заменяется на даташитовские функции. Все 10 бит для технических целей читать не обязательно - достаточно и восьми. Также частоту тактирования АЦП можно поднять до мегагерца - все это даст прирост скорости оцифровки в десять раз. Также не обязательно тормозить мк на время измерений, а производить какие-то вычисления. Ну и сама разводка печатной платы абдурины не предполагает сколь угодно точных измерений с помощью АЦП. Это всего лишь игрушка.
Tomasina, спасибо за ссылки. Попробовал насколько могу в силу не программиста скрестить скетч из последней ссылки со своим, жаль только, проверить в работе пока не могу, но обязательно это сделаю. Разницу должно быть сразу видно по метке, которая должна находиться напротив датчика без запаздывания. Код (C++): uint8_t analog_ref = DEFAULT; void setup() { DDRD = DDRD | B11111100; // устанавливает выходы от 2 до 7 в качестве выходов ADC_init(); // Все настройки АЦП вынесены в отдельную процедуру } void ADC_init() { ADCSRA = 0; // Сбрасываем регистр ADCSRA ADCSRB = 0; // Сбрасываем регистр ADCSRB ADMUX |= (1 << REFS0); // Задаем ИОН //ADMUX |= (1 << ADLAR); // Меняем порядок записи бит, чтобы можно было читать только 8 бит регистра ADCH analog_ref = ADMUX; // Запоминаем состояние регистра - из него мы будем формировать маску для смены входного пина ADMUX |= (0 & 0x07); // Выбираем пин A0 для преобразования // Устанавливаем предделитель - 32 (ADPS[2:0]=101) ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //Битам ADPS2 и ADPS0 присваиваем единицу ADCSRA &= ~ (1 << ADPS1); //Биту ADPS1 присваиваем нули ADCSRA |= (1 << ADATE); // Включаем автоматическое преобразование ADCSRA |= (1 << ADIE); // Разрешаем прерывания по завершении преобразования ADCSRA |= (1 << ADEN); // Включаем АЦП ADCSRA |= (1 << ADSC); // Запускаем преобразование } int currentLEDValue1 = 0; int currentLEDValue2 = 0; volatile int currentSensorValue1 = 0; volatile int currentSensorValue2 = 0; void loop(){ if (currentSensorValue1 > currentSensorValue2){ PORTD = B10000000; // sets digital pins 7 HIGH }else if(currentSensorValue2 > currentSensorValue1) PORTD = B00000000; // sets digital pins 7 LOW } volatile int analogPin = A0; volatile bool trueValue = false; ISR(ADC_vect) { if (trueValue) { int result = ADCL | (ADCH << 8); // ADLAR=1, Получаем 8-битный результат, остальными битами пренебрегаем if (analogPin == A0) { // Если актуальный входной пин A0, то присваиваем значение соответствующей переменной currentSensorValue1 = result; } else { currentSensorValue2 = result; } analogPin += 1; // Перебираем входные пины по кругу (А0...А1 - их может быть больше) if (analogPin > A1) { // Все нужные перебрали... analogPin = A0; // ...возвращаемся к первому }; int pin = analogPin; // Приводим пин вида A0 (14) к удобному для регистра ADMUX - 0. A0=14, A1=15, ... if (pin >= 14) pin -= 14; ADMUX = analog_ref | (pin & 0x07);// Устанавливаем новый вход для преобразования trueValue = false; // Устанавливаем флаг смены входного пина - следующее прерывание пропускаем } else { trueValue = true; // Первый раз пропускаем считывание и устанавливаем флаг на чтение в следующий раз } }
Предыдущий скетч не заработал, мигания какие-то. Пока остановился на установке предделителя 16, работает. Возможно, этого вполне и достаточно в такой приблуде, ускорение в 7 раз по analogRead. Код (C++): void setup(){ DDRD = DDRD | B11111100; // устанавливает выходы от 2 до 7 в качестве выходов ADCSRA |= (1 << ADPS2); //Биту ADPS2 присваиваем единицу - коэффициент деления 16 ADCSRA &= ~ ((1 << ADPS1) | (1 << ADPS0)); //Битам ADPS1 и ADPS0 присваиваем нули } void loop(){ int u1 = analogRead(A1); int u2 = analogRead(A2); if (u1 > u2){ PORTD = B10000000; // sets digital pins 7 HIGH }else if(u2 > u1) PORTD = B00000000; // sets digital pins 7 LOW }