Проблемы при программировании AVR на Си
Проблемы при программировании AVR на Си
Добрый день уважаемые!
Решил создать данную тему поскольку не нашел подходящей.
Предлагаю тут решать проблемы, возникающие, при программировании девайсов на основе AVR, относящихся к умному дому.
Решил создать данную тему поскольку не нашел подходящей.
Предлагаю тут решать проблемы, возникающие, при программировании девайсов на основе AVR, относящихся к умному дому.
Re: Проблемы при программировании AVR на Си
Ну и первая проблема, которая возникла у меня - никак не могу разобраться вроде бы с элементарной задачей - подсчетом количества "сбросов" устройства.
Предисловие: собран девайс на основе всем известного NetAlarm от многоуважаемого Корягина Андрея, который я назвал "Manager of CCTV". Устройство представляет собой контроллер для автономной системы видеонаблюдения загородного участка/дома с управлением через web-интерфейс. Его подробное описание - тема другого топика, однако в списке его возможностей есть следующее: "Позволяет перезагружать контроллер из веб-интерфейса в случае его некорректной работы". Столкнулся с тем, что придумал как перезагружать, а вот как сохранять и отображать количество перезагрузок контроллера на веб-странице - вроде бы просто, но...
Код самого действия на данном этапе такой:
Внешний вид веб-страницы такой:
При первом включении устройства счетчик Count RST=0, после первого сброса равен 1, после второго, третьего и т.д. также равен 1!!! Не могу разобраться почему. Переменная глобальная, значит при первом входе на страничку "Control" она равна 255, поэтому добавлено условие чтобы она была равна 0. Кнопкой отправляем форму - начинается выполнение действия Reset manager, то есть функция HardReset() - в ней к глобальной переменной rstcount добавляется 1 и она записывается в EEPROM. По идее тоже должно происходить при повторной отправке формы, но нет - Count RST остается равен 1!
Предисловие: собран девайс на основе всем известного NetAlarm от многоуважаемого Корягина Андрея, который я назвал "Manager of CCTV". Устройство представляет собой контроллер для автономной системы видеонаблюдения загородного участка/дома с управлением через web-интерфейс. Его подробное описание - тема другого топика, однако в списке его возможностей есть следующее: "Позволяет перезагружать контроллер из веб-интерфейса в случае его некорректной работы". Столкнулся с тем, что придумал как перезагружать, а вот как сохранять и отображать количество перезагрузок контроллера на веб-странице - вроде бы просто, но...
Код самого действия на данном этапе такой:
Код: Выделить всё
// глобальные переменные
uint8_t rstcount;
uint8_t EEMEM EEMEM_RSTCOUNT;
// Hard reset Manager via watchdog
void HardReset()
{ rstcount++;
eeprom_write_block(&rstcount, &EEMEM_RSTCOUNT, sizeof(rstcount));
cli(); // disable interrupts
wdt_enable(WDTO_15MS); // enable watchdog
while(1); // wait for watchdog to reset processor
}
// Фрагмент функции анализа URL
{ ...
if (find_key_val(str,Strbuf,2,"a"))
{ if (Strbuf[0]=='a')
{ ...
//Reset RstCount of manager
if (pg==5)
{ if (find_key_val(str,Strbuf,3,"rstc"))
rstcount = 0;
eeprom_write_block(&rstcount, &EEMEM_RSTCOUNT, sizeof(rstcount));
}
}
}
}
//Reset manager
if (pg==5)
{ if (find_key_val(str,Strbuf,3,"rstm"))
HardReset(); // Reset Manager
}
}
//Сама страница Control
if (page==5)
{ eeprom_read_block(&rstcount, &EEMEM_RSTCOUNT, sizeof(rstcount));
//Reset count of Manager
if (rstcount == 0xFF)
{ rstcount = 0;
}
plen=fill_tcp_data_p(buf,plen,PSTR("<center><h2>Control</h2>Operation time - "));
plen=fill_tcp_data_int(buf,plen,TIMER_DAY);
plen=fill_tcp_data_p(buf,plen,PSTR(" day "));
plen=fill_tcp_data_int(buf,plen,TIMER_HOUR);
plen=fill_tcp_data_p(buf,plen,PSTR(":"));
if(TIMER_MIN<10) plen=fill_tcp_data_p(buf,plen,PSTR("0"));
plen=fill_tcp_data_int(buf,plen,TIMER_MIN);
plen=fill_tcp_data_p(buf,plen,PSTR("<table border=\"0\" width=\"180\"><tr align=\"center\"><td>Count RST="));
plen=fill_tcp_data_int(buf,plen,rstcount);
plen=fill_tcp_data_p(buf,plen,PSTR("</td><form method=\"GET\"><td><input name=\"pg\" type=\"hidden\" value=\"5\">\
<input name=\"a\" type=\"hidden\" value=\"a\"><input name=\"rstc\" type=\"hidden\" value=\"1\"><input type=\"submit\" value=\"Reset\"></td></form></tr></table>\
<form method=\"GET\"><input name=\"pg\" type=\"hidden\" value=\"5\"><input name=\"rstm\" type=\"hidden\" value=\"1\"><input type=\"submit\" value=\"Reset manager\" onclick='ReLoadFunction()'></form></center>\
<script>function ReLoadFunction() {setTimeout(function() {location.reload();}, 5000)}</script>"));
}
При первом включении устройства счетчик Count RST=0, после первого сброса равен 1, после второго, третьего и т.д. также равен 1!!! Не могу разобраться почему. Переменная глобальная, значит при первом входе на страничку "Control" она равна 255, поэтому добавлено условие чтобы она была равна 0. Кнопкой отправляем форму - начинается выполнение действия Reset manager, то есть функция HardReset() - в ней к глобальной переменной rstcount добавляется 1 и она записывается в EEPROM. По идее тоже должно происходить при повторной отправке формы, но нет - Count RST остается равен 1!
Re: Проблемы при программировании AVR на Си
обработчик вроде правильный
вот это в оригинале спрятано в один тег <form> и разделены plen=fill_tcp_data_p ,а что приходит на девайс при нажатии кнопокplen=fill_tcp_data_p(buf,plen,PSTR("</td><form method=\"GET\"><td><input name=\"pg\" type=\"hidden\" value=\"5\">\
<input name=\"a\" type=\"hidden\" value=\"a\"><input name=\"rstc\" type=\"hidden\" value=\"1\"><input type=\"submit\" value=\"Reset\"></td></form></tr></table>\
<form method=\"GET\"><input name=\"pg\" type=\"hidden\" value=\"5\"><input name=\"rstm\" type=\"hidden\" value=\"1\"><input type=\"submit\" value=\"Reset manager\" onclick='ReLoadFunction()'></form></center>\
<script>function ReLoadFunction() {setTimeout(function() {location.reload();}, 5000)}</script>"));
}
Re: Проблемы при программировании AVR на Си
Так-с. В каком оригинале? В NetAlarm такой страницы нет совсем. Тут сделал специально 2 формы чтобы они по отдельности работали, к кнопке "Reset" претензий нет - счетчик реально обнуляет, да и "Reset manager" работает, однако счетчик не инкрементируется... Могу пробросить порт - сами попробуете.alexsis_76 писал(а):вот это в оригинале спрятано в один тег <form> и разделены plen=fill_tcp_data_p ,а что приходит на девайс при нажатии кнопок
Я грешу на запись в EERPROM:
пробовал в HardReset() перед инкрементированием счетчика читать его значение - eeprom_read_block(&rstcount, &EEMEM_RSTCOUNT, sizeof(rstcount));
в итоге - при каждом сбросе мэнеджера прибавляется +5!!! Откуда понять тоже не могу.
Re: Проблемы при программировании AVR на Си
точно такой нет но есть вот такая
примерно как у вас
вместо eeprom_read_block можно использывать eeprom_write_byte у вас uint8_t однобайтовая
void eeprom_write_byte(uint8_t *addr, uint8_t value)
Этот девайс (NetAlarm)я использую тоже , естественно доработанный
а зачем
// Save settings
///////////
if (find_key_val(str,Strbuf,2,"a")) {
if (Strbuf[0]=='a') {
///////////
// Settings
///////////
if (pg==2) {
if (!find_key_val(str,netsettings.myname,TITLE_LENGTH,"name")) {
netsettings.myname[0]='\0';
}
// convert URL spase ('+') to normal space ' '
for (i=0;i<TITLE_LENGTH;i++) {
if (netsettings.myname == '+') {
netsettings.myname = ' ';
}
}
if (find_key_val(str,Strbuf,30,"mac")) {
if (UART_GET_ARG(Strbuf, RXbyte, 0, '-') == 6) {
for (i=0;i<6;i++) {
netsettings.mymac = RXbyte;
}
}
}
примерно как у вас
вместо eeprom_read_block можно использывать eeprom_write_byte у вас uint8_t однобайтовая
void eeprom_write_byte(uint8_t *addr, uint8_t value)
Этот девайс (NetAlarm)я использую тоже , естественно доработанный
а зачем
cli(); // disable interrupts
Последний раз редактировалось alexsis_76 08 апр 2014, 14:59, всего редактировалось 1 раз.
Re: Проблемы при программировании AVR на Си
Понял, спасибо за совет! Вечером попробую. Даже как-то не подумал об этом - слепо скопипастил.
Кстати, раз вы тоже используете клон NetAlarm, то проблему "подвисания" устройства при быстром переключении выходов (вкл./выкл.) не решили? У меня если быстро переключать выход оно начинает тормозить - пинги растягиваются до 4-7 секунд (как раз из-за этого сделал страницу "Control")! Думаю, что это возникает из-за прерывания в прерывании, соответственно в регистры записывается чушь.
Кстати, раз вы тоже используете клон NetAlarm, то проблему "подвисания" устройства при быстром переключении выходов (вкл./выкл.) не решили? У меня если быстро переключать выход оно начинает тормозить - пинги растягиваются до 4-7 секунд (как раз из-за этого сделал страницу "Control")! Думаю, что это возникает из-за прерывания в прерывании, соответственно в регистры записывается чушь.
Я не тестировал без запрета прерываний, но, думаю, ничего хорошего не будет - в какой-то момент выполнение данной функции может прерваться прерыванием тавталогия... в итоге сброса не будет. Вообще случайно нашел данную связку на просторах инета, когда задался поиском софтового варианта сброса AVR.cli(); // disable interrupts
Re: Проблемы при программировании AVR на Си
насчет сторожевого таймера
При разрешении сторожевого таймера его состояние неизвестно и прежде, чем разрешать сторожевой таймер, необходимо выполнить команду WDR
Re: Проблемы при программировании AVR на Си
строжевой таймер его все равно сбросит там внизу бесконечный цикл while(1) из него нет выхода кроме сброса я делал без CLIв какой-то момент выполнение данной функции может прерваться прерыванием
я как то не пробывал их быстро включать выключать , завтра попробуюпроблему "подвисания" устройства при быстром переключении выходов
Re: Проблемы при программировании AVR на Си
а вы датчики оставили возможно дело в этомпроблему "подвисания" устройства при быстром переключении выходов
, даем команду измерения и ждем DS18B20_TCONV_12BIT , потом идем дальшеdelay_ms(DS18B20_TCONV_12BIT);
это гдеДумаю, что это возникает из-за прерывания в прерывании,
Re: Проблемы при программировании AVR на Си
Я оставил так как в исходниках - показалось логичным: настройка на сброс через 1 с при инициализации устройства и после входа в основной цикл сразу сброс Watchdog-а. В функции же сброса мы просто уменьшаем время сброса до минимума и ждем. На самом деле от запрета прерываний в данном случае хуже не будет!alexsis_76 писал(а):насчет сторожевого таймера
Датчики конечно оставил, на данный момент 3 шт., однако переписал немного код считывания температуры, поскольку иначе даже пинг каждую 5-ю секунду жутко тормозил (проверьте у себя, кстати) - теперь все ровненько и читается любой датчик из любой партии (помню были какие-то проблемы):alexsis_76 писал(а):а вы датчики оставили возможно дело в этом
Код: Выделить всё
// Time to read temperature
if (TIMER_DS18B20 == 1)
{ read_temp_meas();
}
if (TIMER_DS18B20 == 3)
{ start_temp_meas();
}
Код: Выделить всё
ISR(TIMER1_OVF_vect)
{ // 100 Hz
TCNT1 = 0x10000 - (F_CPU/1024/100);
// Time correction
if (++TIMER_CORRECT > 13)
{ TIMER_CORRECT = 0;
TCNT1--;
}
// Time of one second
if (++TIMER_ONESEC > 99)
{ TIMER_ONESEC = 0;
// Timer for DS18B20
if (++TIMER_DS18B20 > 5)
{ TIMER_DS18B20 = 0;
}
Это когда микроконтроллер по первому прерыванию от ENC28J60 еще дает ответ (выводит страницу с обновленным состоянием выхода), от ENC28J60 приходит снова прерывание с новым запросом.alexsis_76 писал(а):это где
Re: Проблемы при программировании AVR на Си
Ну в общем перепробовал все... записывал, читал байт. Переменную уже определил как static volatile uint8_t RstCount. И все равно - счетчик останавливается на 1!
Единственное что попробовал - дополнительно читать значение счетчика в функции HardReset(), инкрементировать его и снова записывать в EEPROM:
В итоге при первом сбросе Count RST=5, при втором - Count RST=10, третьем - Count RST=15 и т.д. ОТКУДА ЭТО??? У меня мыслей нет...
Единственное что попробовал - дополнительно читать значение счетчика в функции HardReset(), инкрементировать его и снова записывать в EEPROM:
Код: Выделить всё
// Hard reset Manager via watchdog
void HardReset()
{ RstCount=eeprom_read_byte(&EEMEM_RSTCOUNT);
if (RstCount == 0xFF)
{ RstCount = 0;
}
RstCount++;
//eeprom_write_block(&RstCount, &EEMEM_RSTCOUNT, sizeof(RstCount));
eeprom_write_byte(&EEMEM_RSTCOUNT, RstCount);
cli(); // disable interrupts
wdt_enable(WDTO_15MS); // enable watchdog
while(1); // wait for watchdog to reset processor
}
Re: Проблемы при программировании AVR на Си
так там вроде нет(не было)прерываний , сплошной polling,у меня вроде не виснет, хотя может нажимаю не так быстро
если не жалко скиньте код, посмотрю у себя
я тоже переделал только у меня после старта измерений и завершения преобразования датчики опрашиваются все скопомжутко тормозил
//################# ЧТЕНИЕ ТЕМПЕРАТУРНОГО ДАТЧИКА #########################################
if (FLAG_DS18B20) {
if ( DS18X20_start_meas( DS18X20_POWER_EXTERN,NULL ) == DS18X20_OK ) {//стартуем
FLAG_DS18B20=0;
TIMER_CONERTIONS_DS=DELAY_DS_READY_TEMPERATURE;//ПОСЛЕ ОКОНЧАНИЯ ОПРАШИВАЕМ ДАТЧИКИ
delay_ds_enable=1;// РАЗРЕШАЕМ ТАЙМЕР
}
}
if(DELAY_DS_READY_FLAG){//время ожидания истекло 1 с
for(empty_buf=0;empty_buf<MAXSENSORS;empty_buf++){
DS18B20SensorsValues[empty_buf] = 0;// записуем 0 в буфера
}
for(i=0;i<MAXSENSORS;i++){// перебираем все датчики
if ( DS18X20_read_meas( &gSensorIDs[0], &subzero, &cel, &cel_frac_bits) == DS18X20_OK ) {
DS18B20SensorsValues = (int)cel;
if (subzero == 1)
DS18B20SensorsValues = -1*DS18B20SensorsValues;// если температура отрицательна
}
}
DELAY_DS_READY_FLAG=0;
}
//###############################################################################
если не жалко скиньте код, посмотрю у себя
Re: Проблемы при программировании AVR на Си
Вот теперь и я начал думать - ведь в основной программе прерывания по INT0 не заданы и в ENC28J60.c тоже нет! Видно проектом ошибся, но точно помню что в каком-то проекте (tuxgraphics, наверное) в ENC28J60.c настраивались прерывания по INT0, оттуда и предположения что возникает прерывание в прерывании.alexsis_76 писал(а):так там вроде нет(не было)прерываний , сплошной polling
А можно скрин как у вас бесконечный пинг идет?alexsis_76 писал(а):датчики опрашиваются все скопом
Конечно не жалко, тем более GPL2. Напишите адрес в личке.alexsis_76 писал(а):если не жалко скиньте код, посмотрю у себя
Re: Проблемы при программировании AVR на Си
это какой пингА можно скрин как у вас бесконечный пинг идет?
не все проекты tuxgraphics сделаны как под копирку без обработчикаточно помню что в каком-то проекте (tuxgraphics, наверное)
Re: Проблемы при программировании AVR на Си
Обычный бесконечный пинг из консоли к вашему устройству: ping -t X.X.X.Xalexsis_76 писал(а):это какой пинг
Re: Проблемы при программировании AVR на Си
Вот , правда датчик всего 1 , остальные взял для другого проекта(дефицит), но с 3 работает точно так же , устройство во время пинка само пингует IP, правда как можно видеть тот на пинг не отвечает,пинг раз в секунду, посылает LOG на сервер, в это время я еще нажимал "кнопки" на форме , вроде все нормально,сейчас загружу Вашу программу
- Вложения
-
- ping.rar
- (21.52 КБ) 485 скачиваний
Re: Проблемы при программировании AVR на Си
Ну да - все красиво, хотя все же надо с 3-мя датчиками пробовать (желательно из разных партий), поскольку авторский вариант с 1 датчиком работал тоже хорошо! У меня с авторским вариантом прошивки (с ожиданием после считывания данных с DS18B20 - delay_ms(DS18B20_TCONV_12BIT)) каждый 5-й пинг растягивался. Были проблемы когда DS18B20 из разных партий ("новый" датчик не читался), после убирания задержки, все стало отлично работать. Ах, да еще библиотеки ds18b20 поменял - как раз после этого стало работать замечательно! Так что закупайтесь на том же aliexpess датчиками, последний раз купил десяток за 50 р/шт.
Вечером попробую тоже сделать прямой пинг (непосредственно подключу устройство к PC, сейчас весь трафик через 3G по VPN до домашнего VPN-сервера, затем домашний wi-fi) с "полной" загрузкой устройства.
PS: чувствую надо переименовывать тему в "Делаем клоны NetAlarm под свои нужды"
Вечером попробую тоже сделать прямой пинг (непосредственно подключу устройство к PC, сейчас весь трафик через 3G по VPN до домашнего VPN-сервера, затем домашний wi-fi) с "полной" загрузкой устройства.
PS: чувствую надо переименовывать тему в "Делаем клоны NetAlarm под свои нужды"
Re: Проблемы при программировании AVR на Си
Попробывал загрузить Вашу прошивку , результата ниже
поменял ip адреса , прошил , жуткие тормоза , пинги через раз, при нажатии на ссылки ,открываются те же ссылки ниже,
если сделать вот так
поменял ip адреса , прошил , жуткие тормоза , пинги через раз, при нажатии на ссылки ,открываются те же ссылки ниже,
если сделать вот так
, тормоза пропадают , но страница по прежнему отображается криво, попробывал в 3 браузерахif (TIMER_DS18B20 == 1)
{ //read_temp_meas();
}
Re: Проблемы при программировании AVR на Си
Написал вам в личку, потестируйте.Попробывал загрузить Вашу прошивку , результат ниже
Пинг вечером сделаю на своей версии устройства. У меня ничего подобного не было. Видимо тут компилятор что-то совсем оптимизировал. Каким пользуетесь? Я по старинке WinAVR 2010.
Также попробую отключить оптимизацию в avrdude - главное чтобы размер программы за 32768 байт не вылез!