Jump to content

    
newhumanoid

dsPIC30f4012 Не доходит до главного цикла.

Recommended Posts

Доброго всем!
Нужна помощь. В программировании контроллеров не силен. Можно сказать - село не асфальтированное. Имею общее представление.
Для станка с ЧПУ понадобился сервопривод.
Ранее делал по протоколу плюс/минус 10 вольт. 
Нашел несложный на базе того же контроллера. Но, по протоколу степ/дир.
Спаял. Залил прошиву... И прослезился. Не стартовал проц от слова совсем.
Покопался в исходниках, нашел указания по конфигурации битов.
Поставил. Скомпилил и залил.
Контроллер ожил. Но зациклился. Причем не доходя до основного цикла.
Я так понимаю, что срабатывает какоето прерывание и перезапускает контроллер.
Вот привожу установку битов.
image.thumb.png.0df2ec95f48a6ef7b316521b50e1fadb.png

Вот результат запуска.
Внешняя программа коннектится по UART к MK И попадаю в цикл. Судя по сообщениям из МК, программа не доходит до основного цикла
И перезапускается. Очевидно, прерывание, потому как перезапускает проц не в одном и том же месте.
image.thumb.png.68126ba5a8198a95d8cdd2cfc5ec12db.png

Ну и привожу прогу main
и command
Там видно по printfам что она должна выводить. 
Может поможете советом или ткнете носом что поправить?
С надеждой и благодарностями

 

commands.c main.c

Share this post


Link to post
Share on other sites

Первоисточник. 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 идущих подряд выполняется только один. Иногда два... 
Что то похоже перезапускает проц. (((

Share this post


Link to post
Share on other sites
1 час назад, newhumanoid сказал:

Что то похоже перезапускает проц. (((

Если в разных местах, то: питание (его просадки/помехи), WDT (внешний и внутренний), ...

 

PS: По коду - жесть какая... на дохлом ПИКе и double!  :shok:  типичный признак говнокода....

Share this post


Link to post
Share on other sites

Выкиньте этот говнокод. Нерабочий он.

Во-первых: Изначально (на старте ПО) указатель, по которому пишутся принимаемые 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: Вобщем - этому говнокоду место только в помойке.  :unknw:

PPS: Первое впечатление (от наличия double) полностью подтвердилось...

Share this post


Link to post
Share on other sites

 

29 minutes ago, jcxz said:

PS: По коду - жесть какая... на дохлом ПИКе и double!  :shok:  типичный признак говнокода....

Ну я писал, что не силен в программинге МК. Немного имею представление. Могу только повторить.
Вот начал эксперименты.
взял голій процик подпаял питание, землю, подтянул три ноги к питанию, которіе узнают тип движка, ну и Tx RX PGd PGC...
Ставлю в разные части кода printf и смотрю куда попадает....
Обнаружилась другая бяка.... Уже третий процик после десятка перепрошивок уходит в кирпич (((
Вот такая картинка 
image.thumb.png.d67c76a8187a3ef336f7b52683d51734.png

Чего это они?
Пользуюсь ПИККИТ2 Лайт. Питание на проц не подавал, только от программатора....(((

image.thumb.png.f006da15907dc44bb14ae5a6dd7d5bbd.pngВот так припаяно
 

9 minutes ago, jcxz said:

Выкиньте этот говнокод. Нерабочий он.

Просмотрел по диагонали. Первое что попалось на глаза. Дальше смотреть даже не стал. И так всё ясно.

 

PS: Вобщем - этому говнокоду место только в помойке.  :unknw:

Спасибо огромное что уделили время.
Мда.... Печально... Ну навроде как этот код делался на базе аналогичного серводрайвера, которыые у меня успешно эксплуатируются уже много лет.
различие у них в том, что предыдущий драйвер использовал управление движком по протоколу плюс/минус 10 вольт и только коллекторники и требовал стороннего усилителя (т.е. силовая часть была от стороннего производителя американские АМС). Раньше у китайсав я купил их не дорого, ныне же они только на ИБЭе и цены далеко не гуманные плюс доставка, посему искал другое решение.
А текущий драйвер имеет силовуху на борту и управляется по степ/дир. 

Я сравнивал тексты.  Отличаются тем что текущий умеет крутить бесколлекторники.
Головная прога отличается.
Ну а код по УАРТУ по сути один в один содран. 
Еще раз спасибо за потраченное время. :negative:

Share this post


Link to post
Share on other sites
On 9/19/2021 at 11:09 AM, jcxz said:

начнут писаться с адреса 0 памяти и далее - с инкрементом, снося по ходу дела всё содержимое ОЗУ, которое попадётся по пути.

И что может таким образом превратить процик в кирпич?
Уже 4-й кирпич... (((
 

Share this post


Link to post
Share on other sites

image.thumb.png.00693761f9692041cd130e799356546a.png
Может и не прав. Ну Помимо этого сообщения МПЛАБа ПИККИТ тоже не признает его.

 

36 minutes ago, jcxz said:

почему решили что "кирпич"?

Ну и вот таким образом проц подключаю к программатору. В такой обвязке. Внешнего питания не подаю.
image.thumb.png.9ec017ad65f8bd9af0b16707ae02963c.png

Share this post


Link to post
Share on other sites
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, если вычисление не ограничивают (не ухудшают) работоспособность ?

Share this post


Link to post
Share on other sites
2 minutes ago, dimka76 said:

И чем плох double

Дело в том, что тут без дробных значей не обойтись.
ПИД может быть и в тысячных, а то и десятитысячных единицах.... (((

Share this post


Link to post
Share on other sites
// 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  

Гдето перезапускается таймер?

Edited by aerobus

Share this post


Link to post
Share on other sites
47 минут назад, dimka76 сказал:

rxbuffptr инициализирован в void setup_uart( void )

Ок, смотрел по диагонали.

Там и других чудес хватает, кроме описанных. Вот ещё - putchar() внутри ISR?! Вызов блокирующей функции внутри ISR? Особенно если учесть, что в основном цикле она тоже вызывается и если в МК нет FIFO, то высока вероятность подвисания внутри ISR на некоторое время.

Да и непонятно как она реализована (видимо библиотечная), но автор ничтоже сумняшеся вызывает её и из ISR и из основного цикла (вместе с кучей printf()), ничуть не задумываясь - допускает ли она такое?

Кстати - сейчас только заметил: из другого ISR у автора аж printf("servo-enabled\r\n>"); вызывается!! :shok:  Как оно вообще как-то работало?

 

Цитата

И чем плох double, если вычисление не ограничивают (не ухудшают) работоспособность ?

Так её, работоспособности, то и нет. Как выяснил ТС.

И здесь вроде реалтайм управление какими-то процессами, на МК вроде как не имеющем аппаратной поддержки float/double.

Причём опять-же заметьте - эти операции с плавучкой используются и в ISR-ах и в основном цикле одновременно. Автор в ISR даже операции с double делает!   :shok:

И у меня что-то нет уверенности, что библиотека эмуляции плавающей точки на этом МК реентерабельна.

43 минуты назад, aerobus сказал:

Дело в том, что тут без дробных значей не обойтись.

И что? Для "дробных значений" не нужны ни double ни float.

1 час назад, aerobus сказал:

Ну и вот таким образом проц подключаю к программатору. В такой обвязке. Внешнего питания не подаю.

Если вы вывод "получился кирпич" сделали из того, что "не коннектится программатор/эмулятор", то "неконнектиться" он может по той причине например, что прошивка МК циклически пересбрасывается сразу после старта. Чтобы вывести из такого состояния, обычно boot-пины МК переводят в состояние, запрещающее запуск кода из флешь. И в таком состоянии подключаются эмулятором/программатором.

Также прошивка сразу после старта может переназначать ноги МК, используемые эмулятором. Лечится так же.

Могут быть и другие причины. Эти причины - из опыта с другими МК, в PIC-ах я не силён, но вполне может быть то же самое. Читайте мануал на ваш МК.

Share this post


Link to post
Share on other sites
9 hours ago, jcxz said:

Если вы вывод "получился кирпич" сделали из того, что "не коннектится программатор/эмулятор", то "неконнектиться" он может по той причине например, что прошивка МК циклически пересбрасывается сразу после старта. Чтобы вывести из такого состояния, обычно boot-пины МК переводят в состояние, запрещающее запуск кода из флешь. И в таком состоянии подключаются эмулятором/программатором.

Также прошивка сразу после старта может переназначать ноги МК, используемые эмулятором. Лечится так же.

Могут быть и другие причины. Эти причины - из опыта с другими МК, в PIC-ах я не силён, но вполне может быть то же самое. Читайте мануал на ваш МК.

Здесь нет BOOT пина. Вход в режим программирования осуществляется по ноже RESET, которая програмно не переназначается.

Share this post


Link to post
Share on other sites
52 minutes ago, dimka76 said:

Здесь нет BOOT пина. Вход в режим программирования осуществляется по ноже RESET, которая програмно не переназначается.

Т.е. - кирпич? (((

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.