Не работает программа
- Войдите на сайт для отправки комментариев
Втр, 23/08/2016 - 05:17
Задача проста:
По нажатию на кнопку старт, плавно запускаеться двиг. Делает 15 об. Колличество оборотов отслеживаеться д. Холла. Плавно останавливаеться. Потом задерживаеться. И возвращаеться обратно (пл. пуск, 15 об., плавн. остановка) Время задержки, регулируеться двумя кнопками (+ и -). И выводиться на 1602 экран, через айтуси.
Но почему то, он не работает.
Каждый из компонентов, был проверен в отдельности.
#include <Wire.h> // библиотека для ай2си #include <EEPROM.h> // библиотека ЕРОПАМ #include "LiquidCrystal_I2C.h" LiquidCrystal_I2C lcd(0x27,16,2); // адрес шины #define button_start 2 // пин кнопка - пуск #define button_UP 7 // пин кнопка потенциометр + #define button_DOWN 8 // пин кнопка потенциометр - #define holla 3 // пин датчика холла #define DC_UP 5 // пин движка + #define DC_DOWN 6 // пин движка - byte potenc = 30; // начальное значение потенциометра byte i, y = 0, k = 0; // промежуточные переменные long timer = potenc; // время для обратного отсчета (на всякий случай))) byte adres0 = 0; // адрес еропама для сохранения значений byte a=0; // регистр void setup() { Serial.begin(9600); // порт lcd.init(); // экран potenc = EEPROM.read(adres0); // загрузка значений из еропам lcd.clear(); // очистка экрана lcd.setCursor(0,0); // установка курсора lcd.print("Hello!"); // принт } void loop() { potenciometr(); // вызов метода потенциометр if(digitalRead(button_start)==1 && a==0) // нажатие кнопки - старт { a=1; // сдвиг регистра вперед k=0; // обнуление счетчика вращения вала UP(); // вызов метода запуска двигателя вперед (15 оборотов) delay(potenc*100); // задержка в милисекундлах (заданное время * 100 мс) k=0; // обнуление счетчика DOWN(); // вызов метода запуска двигателя назад (15 оборотов) a=0; // сдвиг назад } } void potenciometr() // потенциометр { if(digitalRead(button_UP)==1) // нажатие кнопки + { lcd.clear(); potenc+=1; // увеличение значения на 1 lcd.setCursor(0,0); lcd.print("Hold = "); lcd.setCursor(12,0); lcd.print(potenc); EEPROM.write(adres0,potenc); // запись значения в еропам } else if(digitalRead(button_DOWN)==1)//нажатие кнопки - { lcd.clear(); potenc-=1; // уменьш знач на 1 lcd.setCursor(0,0); lcd.print("Hold = "); lcd.setCursor(12,0); lcd.print(potenc); EEPROM.write(adres0,potenc); // запись в еропам } } void oborot() // метод замера кол-ва оборотов вала { y = digitalRead(holla); // читаем датчик холла и при каждом у==1 прибавляем единицу к переменной "к" if(y==1) { k++; } } void UP() // метод движения движка вперед { oborot(); // замеряем кол-во оборотов for(i=0;i<=255;i+=5) //медленный запуск { analogWrite(DC_UP,i); analogWrite(DC_DOWN,0); delay(60); } analogWrite(DC_UP,255); analogWrite(DC_DOWN,0); if(k>=15) // 15 оборотов прошло { for(i=255;i>=0;i-=5) // медленная остановка { analogWrite(DC_UP,i); analogWrite(DC_DOWN,0); delay(60); } analogWrite(DC_UP,0); analogWrite(DC_DOWN,0); } } void DOWN() // метод возврата движка, аналогичен методу вперед { oborot(); for(i=0;i<=255;i+=5) { analogWrite(DC_UP,0); analogWrite(DC_DOWN,i); delay(60); } analogWrite(DC_UP,0); analogWrite(DC_DOWN,255); if(k>=34) { for(i=255;i>=0;i-=5) { analogWrite(DC_UP,0); analogWrite(DC_DOWN,i); delay(60); } analogWrite(DC_UP,0); analogWrite(DC_DOWN,0); } }
Как минимум нужно ввести антидребезг. Т.е. это вам "кажется" что вы нажали 1 раз. МК опрашивает порты с большой скоростью, поэтому ему "кажется" что вы отпускаете и нажимаете кнопку много раз. И на еепроме скажется не хорошо, она рассчитана на определенное кол-во циклов записи.
А где в скетче настройка режимов работы пинов, сетап там совершенно пустой?
1 программа, даже не выводит принт. Так что антидребезг тут не причём.
2 еерпом, расчитан на 100 000 циклов.
3 Ок. Сейчас допишу режим работы.
4 Спасибо, отписавшимся.
UPDT:
Ну немножичко ожило.
1 я забыл дописать подсветку экрана. Дописал.
2 Сейчас пишет "Hold = 218". И при каждом обращении, влюсует 1. (219,220,221...)
Вот, исправил:
Вот вам функция из вашего кода
Что она делает? В произвольный момент времени считывает датчик и тупо суммирует. К подсчету оборотов это имеет далекое отношение. Представьте вахтер считает зашедших . В произвольный момент открывает глаза и дверь открыта. Есть зашедший. Но то что есть ситуация, что дверь еще открыта просто вахтер очень быстро моргал глазами и посчитал одного вошедшего за двоих, или тупо проспал кучу входящих, вахтера не волнует.
Так он начинает считать, после начала движения. Или я ошибаюсь?
Многоуважаемые и достопочтенные программеры, не бросайте тапками. Я нуб. Но готов учиться.
вот у вас датчик холла . к примеру о это включено.
digitalRead(holla) идет постоянно. что будет?
0 0 0 0 и.т.д или 1 1 1 1 и.т.д колесо стоит в первом случает магнит напротив датчика, а в другом далеко.
А если 0 0 0 00 0 0 1 1 0 0 то колесо вращается. а если 0 0 0 1 0 0 0 1 0 0 0 очень быстро вращается. И что бы определить 0 или 1 надо команду digitalRead(holla) делать рерулярно и сравнивать с 0 или 1
ПС: Я не готов вас учить, так как мой стиль , это кошмар для других программистов.
Shamanestr, для подсчета оборотов лучше использовать прерывание http://arduino.ru/Reference/AttachInterrupt
настройте его работу по фронту или спаду импульса от датчика и будет считаться только один оборот за оборот.
Цитата из прерываний.http://arduino.ru/Reference/AttachInterrupt
Внутри функции обработки прерывания не работает delay(), значения возвращаемые millis() не изменяются. Возможна потеря данный передаваемых по последовательному соединению (Serial data) в момент выполнения функциии обработки прерывания. Переменные, изменяемые в функции, должным быть объявлены как volatile.
Особенно счетчик оборотов должен быть volatile.
По прерываниям, маленькое дополнение: имеет смысл там изменять переменную ( скажем присваивать 1 глобальную ест-но), а в основном цикле постоянно проверять ее и что то делать. Потом не забыть ее обратно в 0.
Т.е. что то вроде такого получится:
вот это ответище. Буду изучать.
А то остальные посылают на прерывания, а там чорт ногу сломит. Я две недели назад не знал чем мега от уно отличаеться, а они мне про какие то дебри. Мне бы слепить, что бы оно заработало. А тогда появиться мотивация учиться дальше.
Спасибо!
Shamanestr - Я начинал изучать контроллеры с 0, без ардуино. Даже собрал на рассыпухе устройство с контроллером и читал..читал.. потом писал - оно до сих пор работает. А ардуино снижает "порог входа", с ней намного проще, но и многие вещи (те же прерывания) "не доходят". ибо зачем их копать, когда и так "все работает" (на чужом примере переделанном под себя). Только если хочешь сделать что то в "реальном времени" работающее - начинаешь догадываться, что ардуинковские проги не совсем то и без понимания внутреннего устройства не обойтись. У вас как раз такой случай. Прогу за вас никто не напишет. Ну.. за деньги только.
прерываний бояться не надо, там нет ничего сложного, это просто кусок программы который выполняется при подаче или снятии напряжения на пинах, которые эти самые прерывания поддерживают. Еще нужно понимать что если мы в этом куске делаем что то быстро то он будет не заметен на скорости выполнения программы в общем. Вот нам на пример в вашем случае выполняется программа, приходит 1 на пин прерывания, идем в спец программу, прибавляем плюсиком единичку, возвращяемся в основную программу и делаем дальше что надо до следующего прихода единички на пин прерывания. Мне понять прерывания помогло как раз работа с энкодером. в общем не так страшен черт...
Во-во. Прерывания проще для понимания новичков. А вот если фоном организовывать 2 вычислительный процесс, для опроса датчика вращения, то у новичков становятся "анимешные глаза".
Кто нибудь подскажите, почему работает только половина Скетча. сделал доступ к РФИД , всё работает карты считываются, замок срабатывает. добавил код чтобы открыть с радио брелка,. в месте они не работают а по отдельности в полне даже быстро. вот если за ремить с 37 по 56 строки , то часть кода работает. а в месте не хотят. и Ардвинка на код не ругается. подскажите как заставить их работать, чтоб и карта доступа работала и радио брелок.
q
Вот это поворот!