Ламерские вопросы по программированию

Вопросы программирования в системе Ардуино
blur
Сообщения: 23
Зарегистрирован: 03 мар 2017, 08:12

Ламерские вопросы по программированию

Сообщение blur » 10 мар 2017, 02:59

Всем привет. Меня зовут Роман и я начинаю потихоньку осваивать микроконтроллеры Ардуино. буду сюда выкладывать свои вопросы, на которые сам не смогу найти ответа, а вы уж сильно не пинайте. а за советы и правильные ответы - заранее всем спасибо.


blur
Сообщения: 23
Зарегистрирован: 03 мар 2017, 08:12

Re: Ламерские вопросы по программированию

Сообщение blur » 10 мар 2017, 03:26

Итак, вопрос №1.
пытался самостоятельно воссоздать структуру программы, которую Эдуард описал в уроке №38, а именно - программный цикл с периодом 1 сек, разделенный на подциклы по 20мс. воссоздать самостоятельно - удалось, поместил в последний (49-й) подцикл 2 простых команды: инвертирование состояния светодиода и выброс текста в последоавтельный порт. Весь вечер не мог понять, почему в место периодичности 1 сек у меня данные вылетали с периодом, похожим на 20мс - ну очень маленьким... всю голову сломал, пока Эдуард (за что ему отдельное спасибо) не указал на элементарную опечатку. в условии сравнения вместо == было написано = капец :))
в общем ошибку я исправил, и вроде бы все заработало, но... вот мой код (на 19 ножке - АЦП - подключены 2 кнопки с делителями напряжения):

Код: Выделить всё

#include <MsTimer2.h>
#define BUTTON_IN 19
#define LED_PIN 13

byte i, counter20=0, mode=1;//счетчик циклов 2мс, счетчик циклов 20мс, переменная "Режим"
boolean cycle20Ready; //признак начала цикла 20мс
int var;//переменная значение АЦП

void setup() {
  Serial.begin(9600);
MsTimer2::set(2,timerInterrupt);
MsTimer2::start();
pinMode(BUTTON_IN,INPUT_PULLUP); 
pinMode(LED_PIN,OUTPUT);
}

void loop() {
 if (cycle20Ready==true) {//признак начала цикла 20мс, вот тут у меня было =
  cycle20Ready=false;
  counter20++;
   if (counter20>=50)counter20=0; //если завершилось 50 циклов (прошло 50*20=1сек), обнуляем счетчик
     
   if (counter20==49){                  //операции 49-го цикла
    digitalWrite(LED_PIN,!(digitalRead(LED_PIN))); //инвертируем состояние светодиода
    var=analogRead(BUTTON_IN);//считываем значение АЦП
     if (var>600&var<700){//если нажата кнопка №1,
      mode++; //увеличиваем переменную "режим"
      if (mode>100) mode=100;//ограничиваем увеличение
     }
   else if (var>180&var<220) {//если нажата кнопка №2,
     mode--;уменьшаем переменную "режим"
     if (mode<1) mode=1; //ограничиваем уменьшение
     }
   Serial.print(analogRead(BUTTON_IN)); пишем в порт значение АЦП и значение "режим"
   Serial.print("   ");
   Serial.println(mode);
         }
   }
}

void timerInterrupt(){ //цикл 2мс
  i++;
  if (i>=10) {cycle20Ready=true; i=0;}
}


Как писал выше - вроде бы все работает, команды стали выполняться реже, мерцание светодиода теперь различимо глазом)))
НО все равно это происходит не с периодом 1 секунда... примерно 4-5 герц... стал опытным путем подбирать значение counter20, и получается что гдето на 450-500 - состояние светодиода инвертируется раз в секунду...
получается что MsTimer2::set(2,timerInterrupt); - работает с периодом не 2мс, а 0,2мс...
в общем от меня опять никаких конкретных цифр не прозвучало, вечером хочу замерить реальное время с помощью методики Эдуарда, а пока может у кого будут какие мысли? где я опять напартачил? :(

Эдуард
Администратор
Сообщения: 399
Зарегистрирован: 30 окт 2016, 20:53

Re: Ламерские вопросы по программированию

Сообщение Эдуард » 10 мар 2017, 10:48

А программа компилируется без ошибок? Я вижу:

Не отделены комментарии // в строках:

Код: Выделить всё

mode--;уменьшаем переменную "режим"
Serial.print(analogRead(BUTTON_IN)); пишем в порт значение АЦП и значение "режим"

Ошибки в строках сравнения var:

Код: Выделить всё

if (var>600&var<700){//если нажата кнопка №1,
else if (var>180&var<220) {//если нажата кнопка №2,

Для логических операций надо использовать &&.

Больше я ошибок сходу не нашел. Дома проверю на реальной плате.

Я уже писал, это очень сомнительный способ работы с кнопками через АЦП,

Эдуард
Администратор
Сообщения: 399
Зарегистрирован: 30 окт 2016, 20:53

Re: Ламерские вопросы по программированию

Сообщение Эдуард » 10 мар 2017, 18:57

Исправил строки:

Код: Выделить всё

mode--;уменьшаем переменную "режим"
Serial.print(analogRead(BUTTON_IN)); пишем в порт значение АЦП и значение "режим"

Загрузил в плату. Светодиод меняет свое состояние раз в секунду, с такой же частотой передаются данные на монитор последовательного порта.

blur
Сообщения: 23
Зарегистрирован: 03 мар 2017, 08:12

Re: Ламерские вопросы по программированию

Сообщение blur » 13 мар 2017, 02:44

Эдуард писал(а):Исправил строки
...
Загрузил в плату. Светодиод меняет свое состояние раз в секунду, с такой же частотой передаются данные на монитор последовательного порта.


странно это ((. ошибки с каментами возникли из-за того, что код без каментов я принес из дома на работу и с работы писал в фроум. и в этот момент комментариями заполнил программу, в попыхах пару опечаток допустил...

blur
Сообщения: 23
Зарегистрирован: 03 мар 2017, 08:12

Re: Ламерские вопросы по программированию

Сообщение blur » 13 мар 2017, 02:51

Эдуард писал(а):Я уже писал, это очень сомнительный способ работы с кнопками через АЦП,


Эдуард, я согласен с вами, что описаный в уроках метод с использованием библиотеки Button - очень надежен. но я пошел по пути использования АЦП исключительно ради очередного эксперимента, в котором хотел во-первых, сократить кол-во используемых выводов для подключения элементов управления устройством, во-вторых поупражняться в написании элементарных вещей - циклы, условия, синтаксис... в общем набиваю руку потихоньку... чтобы опечаток меньше было ;)

в общем сейчас (как я считаю) - очень хорошо работает начальный режим выставления параметров. есть 3 кнопки: "+", "-", "select".
кнопкой Select выбирается корректируемый параметр (а всего их 3), кнопками + и - - он корректируется. все работает как и планировалось. мне нра.

blur
Сообщения: 23
Зарегистрирован: 03 мар 2017, 08:12

Re: Ламерские вопросы по программированию

Сообщение blur » 14 мар 2017, 03:14

прошу пояснений автора!
Эдуард, в вашем коде (в холодильнике) вообще не могу понять раздел "отсчет времени удержания кнопок + и -"
Вот его кусок:

if (buttonPlus.flagPress == true) {
butPlusTime++;
if (butPlusTime == 0) butPlusTime= 255;
}
я это понимаю так: если кнопка "+" нажата, то увеличиваем счетчик butPlusTime. Если butPlusTime == 0, присваиваем ему значение 255...
никак не могу понять смысл последнего действия.. а учитывая, что butPlusTime имеет тип byte - вообще странно! помогите разобраться.

Эдуард
Администратор
Сообщения: 399
Зарегистрирован: 30 окт 2016, 20:53

Re: Ламерские вопросы по программированию

Сообщение Эдуард » 14 мар 2017, 14:20

Этот блок считает время удержания нажатой кнопки +. При установке параметр меняется на каждое нажатие кнопки, а при удержании кнопки дольше 0,8 секунд, параметр изменяется автоматически. Этот блок просто считает время. Если счетчик butPlusTime переполняется, то его значение ограничивается на максимальном уровне 255. Где-то в другом месте в программе проверяется значение butPlusTime и, если оно больше 0,8 секунд, то параметр изменяется автоматически.

blur
Сообщения: 23
Зарегистрирован: 03 мар 2017, 08:12

Re: Ламерские вопросы по программированию

Сообщение blur » 15 мар 2017, 03:17

аа.. ну понял... значение счетчика после 255 становится 0. и получается что строчкой if (butPlusTime == 0) butPlusTime= 255; мы при достижении значения 255 оставляем его тем же самым. спасибо, разобрался.

blur
Сообщения: 23
Зарегистрирован: 03 мар 2017, 08:12

Re: Ламерские вопросы по программированию

Сообщение blur » 23 мар 2017, 02:58

Вчера обнаружил следующую странность: скетч заливается в плату, запускается алгоритм, все работает. но если при этом открыть монитор порта - плата перегружается... вчера не стал разбираться, подумал что утро вечера мудренее. а утром пришла идея - что может быть это сторожевой таймер плату перегружает? может открытие порта подвешивать выполнение программы или нет? если нет, то из-за чего такое может происходить?

blur
Сообщения: 23
Зарегистрирован: 03 мар 2017, 08:12

Re: Ламерские вопросы по программированию

Сообщение blur » 23 мар 2017, 03:49

ответ на свой вопрос нашел сам. может быть кому пригодится? информация думаю полезная, может Эдуард выделит в отдельную тему?
источник: http://atroshin.ru/ru/content/avtomatic ... -terminala

Именно USB-serial контроллер Arduino перезагружает МК каждый раз, когда терминальная программа (в т.ч. Serial monitor, встроенный в ПО Arduino IDE) устанавливает соединение. Реализовано это следующим образом: у USB-serial контроллера вывод DTR (Data Terminal Ready) связан с выводом RESET. Если программа, работающая с виртуальным последовательным портом, использует DTR, то при установке соединения МК перезагружается.

Возможно избежать автоматической перезагрузки продолжая использовать USB-serial контроллер. Способов достигнуть этого оказалось несколько, как аппаратных, так и программных.

Аппаратные решения сводятся к тому, чтобы не дать сигналу DTR запустить перезагрузку, а именно:
У Arduino Uno R3 есть специальное место на плате, обозначенное как RESET EN, где можно перерезать дорожку, соединяющую DTR и RESET, а при необходимости спаять обратно без особых проблем (см.фото)
Соединить вывод RESET и 5V резистором 120 Ом (для моделей с FTDI USB-serial чипом, напр. Diecimila) [источник]
Соединить вывод RESET и GND конденсатором 10 мкФ (для моделей с USB-serial контроллером на ATmega8U/ATmega16U, напр. Uno) [источник]
Удалить конденсатор, соединяющий вывод DTR USB-serial контроллера и RESET МК (самый жестокий способ) [источник]

Программные решения избегают подачи сигнала DTR:
Модификация кода терминальной программы и/или драйвера последовательного порта с целью исключить использование DTR [источник]
Перепрошивка USB-serial контроллера (для моделей с USB-serial контроллером ATmega8U/ATmega16U) с целью игнорировать сигнал DTR от терминала

blur
Сообщения: 23
Зарегистрирован: 03 мар 2017, 08:12

Re: Ламерские вопросы по программированию

Сообщение blur » 23 мар 2017, 08:29

следующий вопрос: для построения графиков из данных, посылаемых в ком-порт ардуинкой, пытаюсь использовать ActiveX компонент в Excel под названием NetCommOCX. в принципе получается все красиво, график строится, НО. но нужно, чтоб посылаемое значение температуры (например) было всегда из одного и того же количества символов. если это условие выполняется - то данные принимаются экселем и разносятся в столбцы корректно. но значение температуры может быть из разного количества знаков, напр: 9,56; 10,45; 8,7.
поизучав serial.print() особо ответа на вопрос не нашел. пришлось делать через (.)пу, а именно, для компенсации исчезающего символа ПЕРЕД запятой написал так:
если Т<1000 и Е>100, печатаем в порт значение Т
иначе если Т<100 и Т>10, печатаем в порт пробел и значение Т
иначе если Т<10 и Т>1, печатаем в порт два пробела и значение Т

меньше 1 градуса у меня темпера быть не может, алгоритм работает, данные принимаются верно, поэтому оставил так.
НО не могу придумать, что написать для того, чтобы при значении параметра с точностью до десятой доли выводился дополнительный ноль? разноска данных в столбцы сбивается, если вместо 2 знаков после запятой выдается один.
подскажите, пожалуйста.

Эдуард
Администратор
Сообщения: 399
Зарегистрирован: 30 окт 2016, 20:53

Re: Ламерские вопросы по программированию

Сообщение Эдуард » 23 мар 2017, 12:53

Здравствуйте!
Есть стандартная функция вывода данных с форматированием - srintf(). В ней можно задавать число незначащих нулей и много еще чего. В программах верхнего уровня я всегда пользуюсь ей. Но в Ардуино srintf() не работает с плавающей запятой.
Я вижу один способ - преобразовывать данное в текстовую строку и по необходимости добавлять к ней нули. В Serial выводить функцией write(). Только надо не забыть коды возврата каретки (13) и перевода строки (10) добавить.

blur
Сообщения: 23
Зарегистрирован: 03 мар 2017, 08:12

Re: Ламерские вопросы по программированию

Сообщение blur » 24 мар 2017, 00:57

Эдуард, спасибо, буду пробовать.


Вернуться в «Программирование Ардуино»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость