newhumanoid 0 18 сентября, 2021 Опубликовано 18 сентября, 2021 · Жалоба Доброго всем! Нужна помощь. В программировании контроллеров не силен. Можно сказать - село не асфальтированное. Имею общее представление. Для станка с ЧПУ понадобился сервопривод. Ранее делал по протоколу плюс/минус 10 вольт. Нашел несложный на базе того же контроллера. Но, по протоколу степ/дир. Спаял. Залил прошиву... И прослезился. Не стартовал проц от слова совсем. Покопался в исходниках, нашел указания по конфигурации битов. Поставил. Скомпилил и залил. Контроллер ожил. Но зациклился. Причем не доходя до основного цикла. Я так понимаю, что срабатывает какоето прерывание и перезапускает контроллер. Вот привожу установку битов. Вот результат запуска. Внешняя программа коннектится по UART к MK И попадаю в цикл. Судя по сообщениям из МК, программа не доходит до основного цикла И перезапускается. Очевидно, прерывание, потому как перезапускает проц не в одном и том же месте. Ну и привожу прогу main и command Там видно по printfам что она должна выводить. Может поможете советом или ткнете носом что поправить? С надеждой и благодарностями commands.c main.c Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MarkOne 0 19 сентября, 2021 Опубликовано 19 сентября, 2021 · Жалоба файл command.c отсутствует, а лучше приведите ссылку на источник и укажите в каком месте происходит перезапуск Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
newhumanoid 0 19 сентября, 2021 Опубликовано 19 сентября, 2021 · Жалоба Первоисточник. https://www.vbesmens.de/en/downloadse.html Конкретно вот этот проект https://www.vbesmens.de/images/Downloads/UPCX530PowerBoard.zip Перезапуск происходит в разных местах (поэтому грешу на прерывание. Ватчдог вроде выключен). int main(void) { int cs; ModeBLDC=0; setup_io(); // make all i/o pins go the right dir ModeBLDC=!((Hall1)&&(Hall2)&&(Hall3)); // switch to BLDC if one or more of the 3 hall pins are low setErr(); // error on setup_uart(); // setup the serial interface to the PC setup_TMR1(); // set up 1ms timer IEC0bits.T1IE = 1; // Enable interrupts for timer 1 needed for delays in following routines // 1/2 seconds startup delay timer_test = 5000; while (timer_test); if (ModeBLDC) printf("BLDC Mode\r\n"); else printf("DC Mode\r\n"); printf("\r\nPowerup\r\ni/o,uart,timer OK\r\n"); ПЕРЕЗАПУСК ПРОИСХОДИТ НА ЭТОМ ОТРЕЗКЕ обозначу волнистой линией ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setup_pwm(); // start PWM set_pwm(0.0); printf("pwm OK\r\n"); init_pid(); printf("pid OK\r\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setup_encoder(); // 16 bit quadrature encoder module setup printf("encoder OK\r\n"); setup_capture(); // 2 pins with quadrature cmd from PC printf("capture OK\r\n"); // some junk for the serial channel printf(C_VERSION); printf(C_INFO1); printf(C_INFO2); printf(C_INFO3); clearErr(); // led off when init finished restore_setup(); // restore config from eeprom // Read array named "setupEE" from DataEEPROM and place // the result into array in RAM named, "setup" cs = calc_cksum(sizeof(PID)/sizeof(int),(int*)&PID); if ( cs != PID.cksum) { printf("No valid setup found in EEPROM, using defaults.\r\n"); // opps, no valid setup detected init_pid(); clear_EE(); save_setup(); } else { printf("Using setup from eeprom.. ? for help\r\n"); PID.error =0; /* to avoid some bad bugs */ PID.output = 0; PID.command = 0; PID.feedback = 0; print_tuning(); } new_cmd = last_cmd = new_fb = last_fb = 0; set_pwm( 0.0 ); // make sure we dont move on enabling cmd_posn = POSCNT; // make 16bit incr registers match PID.feedback = PID.command = 0L; // make 32 bit counter match new_cmd = last_cmd = new_fb = last_fb = 0; PID.error_i = 0.0; // reset integrator PID.enable = 0; while (1) { // look for serial cmds // doing this while svo is enabled will cause bumps in servo loop // because of serial i/o time ( unless we get smart and move svo loop // into an isr ) if (rxrdy) process_serial_buffer(); test_handle_print(); if(error_flags & 0b00000001) // "maxerror exceeded" error { setErr(); printf("MAXERROR exceeded!\r\n"); } } return 0; } И есть еще одно место в модуле commands.c void print_tuning(void) { // __asm__ volatile ("DISI #0x3FFF"); printf("\rCurrent Settings:\r\n"); Из ВСЕГО СПИСКА ВЫВОДИТСЯ ТОЛЬКО ЭТА СТРОКА (см. принт скрин выше) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ printf("servo enabled = %d\r\n", PID.enable); printf("(p) = %f\r\n", (double)PID.pgain); printf("(i) = %f\r\n", (double)PID.igain); printf("(d) = %f\r\n", (double)PID.dgain); printf("FF(0) = %f\r\n", (double)PID.ff0gain); printf("FF(1) = %f\r\n", (double)PID.ff1gain); printf("dead(b)and = %f\r\n",(double)PID.deadband); printf("(m)ax Output = %.2f\r\n",(double)PID.maxoutput); printf("(f)ault error = %f\r\n", (double)PID.maxerror); printf("(x)pc cmd multiplier = %hu\r\n", PID.multiplier); printf("(t)icks per servo cycle= %hu\r\n",PID.ticksperservo); printf("(h)all timeout= %lu\r\n",PID.HallTimeout); printf("char(g)e elcos= %u\r\n",PID.DoChargeElcos); printf("phase (a)dvance= %u\r\n",PID.PhaseAdvance); printf("SVM (c)ycle= %u\r\n",PID.SVMCycle); // DISICNT = 0; } Т.е. из всех операторов printf идущих подряд выполняется только один. Иногда два... Что то похоже перезапускает проц. ((( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 19 сентября, 2021 Опубликовано 19 сентября, 2021 · Жалоба 1 час назад, newhumanoid сказал: Что то похоже перезапускает проц. ((( Если в разных местах, то: питание (его просадки/помехи), WDT (внешний и внутренний), ... PS: По коду - жесть какая... на дохлом ПИКе и double! типичный признак говнокода.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 19 сентября, 2021 Опубликовано 19 сентября, 2021 · Жалоба Выкиньте этот говнокод. Нерабочий он. Во-первых: Изначально (на старте ПО) указатель, по которому пишутся принимаемые UART байты (rxbuffptr) не инициализирован. И, после инита UART, входящие байты (не равные '\r' и '\n') начнут писаться с адреса 0 памяти и далее - с инкрементом, снося по ходу дела всё содержимое ОЗУ, которое попадётся по пути. Инит rxbuffptr делается только при приёме кода '\r'. Так что - чтобы не портило ОЗУ, нужно чтобы первым символом пришедшим в UART после старта ПО был код '\r' (13). В этом случае повезёт. У автора сего поделия видимо всегда первым шёл '\r', а у вас - что-то другое (может байты мусора). Во-вторых: "парсер" команд и ISR приёма по UART.RX никак не синхронизированы между собой. Т.е. - после приёма '\r' в ISR UART должна запуститься обработка принятой строки в process_serial_buffer(). Но при этом ISR UART.RX продолжает работать. И если сразу после '\r' начнут поступать новые байты (в то время как process_serial_buffer() ещё не успел обработать предыдущие), то содержимое предыдущей принятой строки будет порушено (новые символы приклеятся в конец предыдущей строки). В-третьих: reset_buffer() в после завершения обработки некоторых команд вызывается дважды. А это значит, что в некоторых случаях, если не повезёт, то начало следующей принимаемой UART строки команды может быть потеряно (вторым вызовом reset_buffer()). В-четвёртых: нигде нет ни одного volatile. При взаимодействии основной задачи и ISR. А значит при включении оптимизации, добавятся новые "сюрпризы". Такое поделие может ещё более-менее как-то "работать" только с полностью отключенной оптимизацией кода в компиляторе. Просмотрел по диагонали. Первое что попалось на глаза. Дальше смотреть даже не стал. И так всё ясно. PS: Вобщем - этому говнокоду место только в помойке. PPS: Первое впечатление (от наличия double) полностью подтвердилось... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aerobus 0 19 сентября, 2021 Опубликовано 19 сентября, 2021 · Жалоба 29 minutes ago, jcxz said: PS: По коду - жесть какая... на дохлом ПИКе и double! типичный признак говнокода.... Ну я писал, что не силен в программинге МК. Немного имею представление. Могу только повторить. Вот начал эксперименты. взял голій процик подпаял питание, землю, подтянул три ноги к питанию, которіе узнают тип движка, ну и Tx RX PGd PGC... Ставлю в разные части кода printf и смотрю куда попадает.... Обнаружилась другая бяка.... Уже третий процик после десятка перепрошивок уходит в кирпич ((( Вот такая картинка Чего это они? Пользуюсь ПИККИТ2 Лайт. Питание на проц не подавал, только от программатора....(((Вот так припаяно 9 minutes ago, jcxz said: Выкиньте этот говнокод. Нерабочий он. Просмотрел по диагонали. Первое что попалось на глаза. Дальше смотреть даже не стал. И так всё ясно. PS: Вобщем - этому говнокоду место только в помойке. Спасибо огромное что уделили время. Мда.... Печально... Ну навроде как этот код делался на базе аналогичного серводрайвера, которыые у меня успешно эксплуатируются уже много лет. различие у них в том, что предыдущий драйвер использовал управление движком по протоколу плюс/минус 10 вольт и только коллекторники и требовал стороннего усилителя (т.е. силовая часть была от стороннего производителя американские АМС). Раньше у китайсав я купил их не дорого, ныне же они только на ИБЭе и цены далеко не гуманные плюс доставка, посему искал другое решение. А текущий драйвер имеет силовуху на борту и управляется по степ/дир. Я сравнивал тексты. Отличаются тем что текущий умеет крутить бесколлекторники. Головная прога отличается. Ну а код по УАРТУ по сути один в один содран. Еще раз спасибо за потраченное время. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aerobus 0 20 сентября, 2021 Опубликовано 20 сентября, 2021 · Жалоба On 9/19/2021 at 11:09 AM, jcxz said: начнут писаться с адреса 0 памяти и далее - с инкрементом, снося по ходу дела всё содержимое ОЗУ, которое попадётся по пути. И что может таким образом превратить процик в кирпич? Уже 4-й кирпич... ((( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 20 сентября, 2021 Опубликовано 20 сентября, 2021 · Жалоба 8 минут назад, aerobus сказал: И что может таким образом превратить процик в кирпич? А почему решили что "кирпич"? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aerobus 0 20 сентября, 2021 Опубликовано 20 сентября, 2021 · Жалоба Может и не прав. Ну Помимо этого сообщения МПЛАБа ПИККИТ тоже не признает его. 36 minutes ago, jcxz said: почему решили что "кирпич"? Ну и вот таким образом проц подключаю к программатору. В такой обвязке. Внешнего питания не подаю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 42 20 сентября, 2021 Опубликовано 20 сентября, 2021 · Жалоба On 9/19/2021 at 11:09 AM, jcxz said: Во-первых: Изначально (на старте ПО) указатель, по которому пишутся принимаемые UART байты (rxbuffptr) не инициализирован. rxbuffptr инициализирован в void setup_uart( void ) On 9/19/2021 at 11:09 AM, jcxz said: В-четвёртых: нигде нет ни одного volatile. // serial.c volatile char rxbuff[30]; // global rx buffer for serial data volatile char *rxbuffptr; // local input ptr for storing data volatile short int rxrdy; // flag to indicate a line of data is available in On 9/19/2021 at 11:09 AM, jcxz said: PPS: Первое впечатление (от наличия double) полностью подтвердилось... И чем плох double, если вычисление не ограничивают (не ухудшают) работоспособность ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aerobus 0 20 сентября, 2021 Опубликовано 20 сентября, 2021 · Жалоба 2 minutes ago, dimka76 said: И чем плох double Дело в том, что тут без дробных значей не обойтись. ПИД может быть и в тысячных, а то и десятитысячных единицах.... ((( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aerobus 0 20 сентября, 2021 Опубликовано 20 сентября, 2021 (изменено) · Жалоба // Initialization of timer 1 as a periodic interrupt // each 0.1 ms (10khz) void setup_TMR1(void) { printf("\r\n\555555555555\r\n"); T1CON = 0x0020; // internal Tcy/64 clock TMR1 = 0; #define PR1PRESET (FCY/64/10000) PR1 = PR1PRESET; // 0.1 ms interrupts (100us) T1CONbits.TON = 1; // turn on timer 1 _T1IP = 6; } Вот вставил в таймер строчку принт... И натыкал в начале строк \r\n\ Вот что получаю при коннектк 23:24:52 23:24:52 23:24:52 m555555555 23:24:52 23:24:52 23:24:52 23:24:52 servo-enabled~~~~ 23:24:52 23:24:52 > 23:24:52 23:24:52 m555555555 23:24:52 23:24:52 23:24:52 23:24:52 servo-enabled~~~~ 23:24:52 23:24:53 > 23:24:53 23:24:53 m555555555 23:24:53 23:24:53 23:24:53 23:24:53 servo-enabled~~~~ 23:24:53 23:24:53 > 23:24:53 23:24:53 m555555555 23:24:53 23:24:53 23:24:53 23:24:53 m555555555 23:24:53 23:24:53 23:24:53 23:24:53 servo-enabled~~~~ 23:24:53 23:24:53 > 23:24:53 23:24:53 DC Mode 23:24:53 23:24:53 23:24:53 23:24:53 Powerup 23:24:53 23:24:53 i/o,uart,timer OK 23:24:53 23:24:53 23:24:53 23:24:53 m555555555 23:24:53 23:24:53 23:24:53 23:24:53 servo-enabled~~~~ 23:24:53 23:24:54 > 23:24:54 23:24:54 m555555555 23:24:54 23:24:54 23:24:54 23:24:54 m555555555 23:24:54 23:24:54 23:24:54 23:24:54 m555555555 23:24:54 23:24:54 23:24:54 23:24:54 servo-enabled~~~~ 23:24:54 23:24:55 > 23:24:55 23:24:55 m555555555 23:24:55 23:24:55 23:24:55 23:24:55 servo-enabled~~~~ 23:24:55 23:24:55 > 23:24:55 23:24:55 m555555555 23:24:55 23:24:55 23:24:55 23:24:55 servo-enabled~~~~ 23:24:55 23:24:56 > 23:24:56 23:24:56 DC Mode 23:24:56 23:24:56 23:24:56 23:24:56 Powerup 23:24:56 23:24:56 i/o,uart,timer OK 23:24:56 23:24:56 23:24:56 23:24:56 m555555555 23:24:56 23:24:56 23:24:56 23:24:56 m555555555 23:24:56 23:24:56 23:24:56 23:24:56 servo-enabled~~~~ 23:24:56 23:24:56 ю 23:24:56 23:24:56 m555555555 23:24:56 23:24:56 23:24:56 23:24:56 servo-enabled~~~~ 23:24:56 23:24:57 > 23:24:57 23:24:57 m555555555 23:24:57 23:24:57 23:24:57 23:24:57 servo-enabled~~~~ 23:24:57 23:24:57 > 23:24:57 23:24:57 DC Mode 23:24:57 23:24:57 23:24:57 23:24:57 Powerup 23:24:57 23:24:57 i/o,uart,timer OK 23:24:57 23:24:57 23:24:57 23:24:57 m555555555 23:24:57 23:24:57 23:24:57 23:24:57 servo-enabled~~~~ 23:24:57 23:24:58 > 23:24:58 23:24:58 DC Mode 23:24:58 23:24:58 23:24:58 23:24:58 Powerup 23:24:58 23:24:58 i/o,uart,timer OK 23:24:58 23:24:58 23:24:58 23:24:58 m555555555 23:24:58 23:24:58 23:24:58 23:24:58 servo-enabled~~~~ 23:24:58 23:24:58 > 23:24:58 23:24:58 DC Mode 23:24:58 23:24:58 23:24:58 23:24:58 Powerup 23:24:58 23:24:58 i/o,uart,timer OK 23:24:58 23:24:59 23:24:59 23:24:59 m555555555 23:24:59 23:24:59 23:24:59 23:24:59 servo-enabled~~~~ 23:24:59 Гдето перезапускается таймер? Изменено 20 сентября, 2021 пользователем aerobus Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 20 сентября, 2021 Опубликовано 20 сентября, 2021 · Жалоба 47 минут назад, dimka76 сказал: rxbuffptr инициализирован в void setup_uart( void ) Ок, смотрел по диагонали. Там и других чудес хватает, кроме описанных. Вот ещё - putchar() внутри ISR?! Вызов блокирующей функции внутри ISR? Особенно если учесть, что в основном цикле она тоже вызывается и если в МК нет FIFO, то высока вероятность подвисания внутри ISR на некоторое время. Да и непонятно как она реализована (видимо библиотечная), но автор ничтоже сумняшеся вызывает её и из ISR и из основного цикла (вместе с кучей printf()), ничуть не задумываясь - допускает ли она такое? Кстати - сейчас только заметил: из другого ISR у автора аж printf("servo-enabled\r\n>"); вызывается!! Как оно вообще как-то работало? Цитата И чем плох double, если вычисление не ограничивают (не ухудшают) работоспособность ? Так её, работоспособности, то и нет. Как выяснил ТС. И здесь вроде реалтайм управление какими-то процессами, на МК вроде как не имеющем аппаратной поддержки float/double. Причём опять-же заметьте - эти операции с плавучкой используются и в ISR-ах и в основном цикле одновременно. Автор в ISR даже операции с double делает! И у меня что-то нет уверенности, что библиотека эмуляции плавающей точки на этом МК реентерабельна. 43 минуты назад, aerobus сказал: Дело в том, что тут без дробных значей не обойтись. И что? Для "дробных значений" не нужны ни double ни float. 1 час назад, aerobus сказал: Ну и вот таким образом проц подключаю к программатору. В такой обвязке. Внешнего питания не подаю. Если вы вывод "получился кирпич" сделали из того, что "не коннектится программатор/эмулятор", то "неконнектиться" он может по той причине например, что прошивка МК циклически пересбрасывается сразу после старта. Чтобы вывести из такого состояния, обычно boot-пины МК переводят в состояние, запрещающее запуск кода из флешь. И в таком состоянии подключаются эмулятором/программатором. Также прошивка сразу после старта может переназначать ноги МК, используемые эмулятором. Лечится так же. Могут быть и другие причины. Эти причины - из опыта с другими МК, в PIC-ах я не силён, но вполне может быть то же самое. Читайте мануал на ваш МК. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 42 21 сентября, 2021 Опубликовано 21 сентября, 2021 · Жалоба 9 hours ago, jcxz said: Если вы вывод "получился кирпич" сделали из того, что "не коннектится программатор/эмулятор", то "неконнектиться" он может по той причине например, что прошивка МК циклически пересбрасывается сразу после старта. Чтобы вывести из такого состояния, обычно boot-пины МК переводят в состояние, запрещающее запуск кода из флешь. И в таком состоянии подключаются эмулятором/программатором. Также прошивка сразу после старта может переназначать ноги МК, используемые эмулятором. Лечится так же. Могут быть и другие причины. Эти причины - из опыта с другими МК, в PIC-ах я не силён, но вполне может быть то же самое. Читайте мануал на ваш МК. Здесь нет BOOT пина. Вход в режим программирования осуществляется по ноже RESET, которая програмно не переназначается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aerobus 0 21 сентября, 2021 Опубликовано 21 сентября, 2021 · Жалоба 52 minutes ago, dimka76 said: Здесь нет BOOT пина. Вход в режим программирования осуществляется по ноже RESET, которая програмно не переназначается. Т.е. - кирпич? ((( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться