непонятное зависание программы через минуту

russo
Offline
Зарегистрирован: 20.11.2014

Сделал радиоуправляемую платформу, на про мини ардуине.

Примерно через минуту машинка зависает, не принимает моманды управления и на дисплее видно как начинают прорисоывваться пиксели очень медленно. 

Прием написан по прерыванию в формате пакетов старлайн, для помехозащищенности.

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

//#include <Adafruit_GFX.h>      // Core graphics library
//#include <Adafruit_ST7735.h>   // Hardware-specific library
//#include <SPI.h>x_position
#include <avr/wdt.h>


//#define sclk 13
//#define mosi 11
#define cs   10
#define dc   9
#define rst  8                 // you can also connect this to the Arduino reset

#define RX 2

#define D1 3          // Направление вращение двигателя 1
#define M1 5          // ШИМ вывод для управления двигателем 1
#define D2 7          // Направление вращение двигателя 2
#define M2 6          // ШИМ вывод для управления двигателем 2

#define forward 0     //направлене движения в перед
#define back    1     //напрвление движения назад

//bool direction = 0;       // Текущее направление вращения       
int value;                  // Текущее значение ШИМ
int left_motor;             //скорость левого мотора
int riht_motor;             //скорость правого мотора
int left_motor_temp;        //
int riht_motor_temp;        //
int x_position;             //
int y_position;             //
bool left_napravlenie;      //напрвление вращения 
bool riht_napravlenie;      //напрвление вращения 
bool flag_stop_motor;       //флаг гстановки двигателей по истечении 250 млсек 
unsigned char flag_datacar; //флаг прилета новых данных


//Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);

volatile byte level=255;
volatile unsigned long last, len;
byte p_level;
unsigned long p_len, p_len_prev;
volatile unsigned char str[2];    //для вывода на дисплей

unsigned char sernom[4] = {0x12, 0x34, 0x56, 0x78};  //серийник машинки
unsigned char datacar[4];                            //данные прилетевших пакетов для управления машинкой
                                                     //datacar[0] - данные скорости левой стороны
                                                     //datacar[1] - данные скорости правой стороны

volatile unsigned int tcnt2;                         //для таймера2
volatile char count;                                 //для подсчета переполнений таймера2
volatile unsigned int time_no_comand;                //для измерения милисекунд с момента прилета команды
volatile unsigned int time;  
volatile bool flag_time;

volatile struct
{
  volatile unsigned char state;
  unsigned char data[3], dat_bit;     
} came;

struct
{
  byte state;
  unsigned long TE;
  byte pre_count, data[8], dat_bit;
} keeloq;

struct
{
  byte state;
  byte pre_count, data[8], dat_bit;
} starline;

void setbit(byte *data, byte n)
{
  data[n/8]|=1<<(7-n%8);
}

#define KL_MIN_PRE_COUNT 4
#define KL_MAX_TE 500
#define KL_MIN_TE 300
#define KL_MAX_BITS 64

void process_keeloq()
{
  switch(keeloq.state)
  {
    case 0:
      if(p_level) break;
      keeloq.state=1;
      keeloq.pre_count=0;
      break;

    case 1: //pre+hdr
      if(p_len>=KL_MIN_TE && p_len<=KL_MAX_TE) keeloq.pre_count++;
      else if(!p_level && p_len>=KL_MIN_TE*10 && p_len<=KL_MAX_TE*10 && keeloq.pre_count>=KL_MIN_PRE_COUNT)
      {
        keeloq.TE=p_len/10;
        keeloq.state=2;
        keeloq.dat_bit=0;
        keeloq.data[0]=0x00;
        keeloq.data[1]=0x00;
        keeloq.data[2]=0x00;
        keeloq.data[3]=0x00;
        keeloq.data[4]=0x00;
        keeloq.data[5]=0x00;
        keeloq.data[6]=0x00;
        keeloq.data[7]=0x00;
      }
        else
      {
        keeloq.state=0;
        break;
      }
      break;

    case 2: //dat
      if(!p_level) break;

      if(p_len<keeloq.TE/2 || p_len>keeloq.TE*3)
      {
        keeloq.state=0;
        break;
      }

      if(p_len<=keeloq.TE+keeloq.TE/2) setbit(keeloq.data, keeloq.dat_bit);
      if(++keeloq.dat_bit==KL_MAX_BITS) keeloq.state=100;
      break;
  }
}

#define SL_MIN_PRE_COUNT 4
#define SL_MAX_PRE 1150
#define SL_MIN_PRE 850
#define SL_MAX_ZERO 350
#define SL_MIN_ZERO 100
#define SL_MAX_ONE 700
#define SL_MIN_ONE 400
#define SL_MIN_BITS 16
#define SL_MAX_BITS 64

void process_starline()
{
  byte b;

  switch(starline.state)
  {
    case 0:
      if(p_level) break;
      starline.state=1;
      starline.pre_count=0;
      break;

    case 1: //pre
      if(p_len>=SL_MIN_PRE && p_len<=SL_MAX_PRE) starline.pre_count++;
      else if(p_len<SL_MIN_PRE && starline.pre_count>=SL_MIN_PRE_COUNT)
      {
        starline.state=2;
        starline.dat_bit=0;
        starline.data[0]=0x00;
        starline.data[1]=0x00;
        starline.data[2]=0x00;
        starline.data[3]=0x00;
        starline.data[4]=0x00;
        starline.data[5]=0x00;
        starline.data[6]=0x00;
        starline.data[7]=0x00;
      }
        else
      {
        starline.state=0;
        break;
      }
      break;

    case 2: //dat
      if(p_level) break;
      
      if(p_len_prev>=SL_MIN_ONE && p_len_prev<=SL_MAX_ONE &&
         p_len>=SL_MIN_ONE && p_len<=SL_MAX_ONE) b=0;
       else
      if(p_len_prev>=SL_MIN_ZERO && p_len_prev<=SL_MAX_ZERO &&
         p_len>=SL_MIN_ZERO && p_len<=SL_MAX_ZERO) b=1;
      else
      {
        //if(starline.dat_bit>=SL_MIN_BITS) starline.state=100;
        //  else 
          starline.state=0;
        break;
      }

      if(b) setbit(starline.data, starline.dat_bit);
      if(++starline.dat_bit==SL_MAX_BITS) starline.state=100;
      break;
  }
}
/*
void dump_hex(byte *buf, byte bits)
{
  byte a;
  
  for(a=0; a<(bits+7)/8; a++)
  {
    if(buf[a]<=0x0f) Serial.print('0');
    Serial.print(buf[a], HEX);
    Serial.print(" ");
  }
  Serial.println("");
}
*/
void rx_int()
{
  if(level!=255) return;
  
  len=micros()-last;
  last=micros();
  
  if(digitalRead(RX)==HIGH) level=0;
    else level=1; 
}

void setup()
{ 
  attachInterrupt(0, rx_int, CHANGE);
//  tft.initR(INITR_REDTAB); 
  //Serial.begin(115200); 
  //while(!Serial);
  
//  Serial.begin(57600);
  
  pinMode(D1, OUTPUT);
  pinMode(D2, OUTPUT); 
  wdt_enable(WDTO_250MS);
/*  
  tft.invertDisplay(false);
  tft.fillScreen(ST7735_BLACK);
  tft.setCursor(0, 0);
  tft.setTextColor(ST7735_BLUE);
  tft.setTextSize(1);
  tft.println("      SUPERCAR       ");
  tft.setCursor(0, 10);
  tft.setTextColor(ST7735_WHITE);
  tft.println("   ARDUINO PRO MINI");
  tft.setCursor(0, 20);
  tft.println("      ATMEGA328A");
  
  tft.setTextColor(ST7735_RED);
  tft.setCursor(0, 150);
  tft.print("   V bat = 6.25 v ");
 */ 
  //wdt_enable(WDTO_1S);    //включаем ватч дог с периодом 1000 мсек
  //interrupts();
} 

byte a;

void loop()
{ 
  wdt_reset();
/*  
  if((millis() -  time)>500)
  {
      time = millis();
      flag_time = !flag_time;
      
      if(flag_time)
      {
        tft.setCursor(0, 150);
        tft.print("   V bat = 6.25 v ");
      }
      else tft.fillRect(0, 150, 130, 8,  ST7735_BLACK);
  }
*/  
 //если более секунды нет команд - отключаем двигатели 
  if(!flag_stop_motor & (millis() -  time_no_comand) > 1000)
  {
     flag_stop_motor = 1;
     left_motor = 0;
     riht_motor = 0;
     analogWrite(M1, 0x00);       // выключаем моторы, если нет команд с пульта более 250 миллисекунд
     analogWrite(M2, 0x00);
     digitalWrite(D1, forward);  // Задаем направление вращения
     digitalWrite(D2, forward); 
 /*    
     tft.fillRect(0, 110, 130, 8,  ST7735_BLACK);
     tft.setTextColor(ST7735_GREEN);
     tft.setCursor(0, 110);
     tft.print(left_napravlenie);
     tft.print("  ");
     tft.print("LEFT ");
     tft.print(left_motor);
//     wdt_reset();
     tft.fillRect(0, 130, 130, 8,  ST7735_BLACK);
     tft.setTextColor(ST7735_GREEN);
     tft.setCursor(0, 130);
     tft.print(riht_napravlenie);
     tft.print("  ");
     tft.print("RIHT ");
     tft.print(riht_motor);
     */
  }
 //----------------------------------------------------------------------
 
  if(flag_datacar)
  {
      
     time_no_comand = millis();  //засекаем время после прилета команды
     flag_stop_motor = 0;        //сброс флага остановки двигателей
  /*   
     tft.fillRect(0, 70, 130, 8,  ST7735_BLACK);
     tft.setTextColor(ST7735_GREEN);
     tft.setCursor(0, 70);
     tft.print("   PRIEM KOMAND  ");
     
   */  
     wdt_reset();
     x_position = (starline.data[4]*256 + starline.data[5]);  //значение 0-1024
     y_position = (starline.data[6]*256 + starline.data[7]);  //значение 0-1024
   /*  
     tft.fillRect(0, 60, 130, 8,  ST7735_BLACK);
     tft.setTextColor(ST7735_GREEN);
     tft.setCursor(0, 60);
     tft.print("X_pos ");
     tft.print(x_position);
     tft.print("  Y_pos ");
     tft.print(y_position);
   */  
   //  if(x_position > 517)
   //  {
         left_motor_temp = y_position + ((x_position - 512)/2);
         riht_motor_temp = y_position - ((x_position - 512)/2);
    // }
    //   else if(x_position < 507)
    //   {
    //     left_motor_temp = y_position - (x_position - 512);
    //     riht_motor_temp = y_position + (x_position - 512);
    //   }
    //   else
    //   {
    //     left_motor_temp = y_position;
    //     riht_motor_temp = y_position;
    //   }
       
     if(left_motor_temp > 1023) left_motor_temp = 1021;
     if(left_motor_temp < 1)    left_motor_temp = 3;
     if(riht_motor_temp > 1023) riht_motor_temp = 1021;
     if(riht_motor_temp < 1)    riht_motor_temp = 3;
     
     left_motor = (abs(left_motor_temp - 512))/2;    
     riht_motor = (abs(riht_motor_temp - 512))/2;
     
     if(left_motor_temp > 512)
     {
       left_napravlenie = 1;
       left_motor = 255 - left_motor;
     }
     else
     {
       left_napravlenie = 0;
     }  
     
     if(riht_motor_temp > 512)
     {
       riht_napravlenie = 1;
       riht_motor = 255 - riht_motor;
     } 
     else
     {
       riht_napravlenie = 0;
     }
          
     
     
     wdt_reset();
    
   /*  
     tft.fillRect(0, 110, 130, 8,  ST7735_BLACK);
     tft.setTextColor(ST7735_GREEN);
     tft.setCursor(0, 110);
     tft.print(left_napravlenie);
     tft.print("  ");
     tft.print("LEFT ");
     tft.print(left_motor);
  //   wdt_reset();
     tft.fillRect(0, 130, 130, 8,  ST7735_BLACK);
     tft.setTextColor(ST7735_GREEN);
     tft.setCursor(0, 130);
     tft.print(riht_napravlenie);
     tft.print("  ");
     tft.print("RIHT ");
     tft.print(riht_motor);
   //  wdt_reset();
    */   
     digitalWrite(D1, left_napravlenie);  // Задаем направление вращения
     digitalWrite(D2, riht_napravlenie); 
     analogWrite(M1, left_motor);       // Задаем скорость вращения
     analogWrite(M2, riht_motor);
             
     flag_datacar = 0;
     
     wdt_reset();
  }  
  
  if(level!=255)
  {
 //   noInterrupts();
    p_level=level;
    p_len=len;
    len=0;
    level=255;
 //   interrupts();
    wdt_reset();
    process_keeloq();
    process_starline();
    
    p_len_prev=p_len;
  }
 /* 
  if(keeloq.state==100)
  {
    //Serial.print("KEELOQ: ");
    //dump_hex(keeloq.data, 64);
     tft.setCursor(0, 40);
     tft.setTextColor(ST7735_RED);
     tft.fillRect(0, 40, 130, 8,  ST7735_BLACK);
     tft.println("      KEELOG ");
     tft.fillRect(0, 50, 130, 8,  ST7735_BLACK);
//     wdt_reset();
     tft.setCursor(0, 50);
     for(a=0; a<8; a++)
     {
       if(a==0) tft.print(" ");
       if(a==4) tft.print(" ");
       //if(a==7) tft.print(" ");
       tft.print(keeloq.data[a], HEX);
      
     }
     
//    wdt_reset();
    keeloq.state=0;
  }
 */ 
  if(starline.state==100)
  {
//     Serial.print("STARLINE[");
//     Serial.print(starline.dat_bit);
//     Serial.print("]: ");
//     dump_hex(starline.data, starline.dat_bit);
/*     
     tft.setCursor(0, 40);
     tft.setTextColor(ST7735_BLUE);
     tft.fillRect(0, 40, 130, 8,  ST7735_BLACK);
     tft.print("  STARLINE ");
     tft.fillRect(0, 50, 130, 8,  ST7735_BLACK);
     wdt_reset();
     tft.setCursor(0, 50);
     //tft.setTextColor(ST7735_BLUE);
     for(a=0; a<8; a++)
     {
       if(a==0) tft.print(" ");
       if(a==4) tft.print(" ");
       tft.print(starline.data[a], HEX);
     }
     */
     if((starline.data[0]==sernom[0])&&(starline.data[1]==sernom[1])&&(starline.data[2]==sernom[2])&&(starline.data[3]==sernom[3])) flag_datacar = 1;    //прилетели новые данные, нужно обработать
    starline.state=0;
  }
}

 

russo
Offline
Зарегистрирован: 20.11.2014

сторожевой таймер не работает, не понял почему.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

 Виснет судя по всему через 65 секунд :) 52, 53 строка не мала ли u_int для хранения миллис() ?

russo
Offline
Зарегистрирован: 20.11.2014

Спасибо, исправил на unsigned long

Хотел уже на 18F2520 камне переделать машинку, давно лежит, забросил в дальний угол.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Круто... Как вы это читаете и находите... Это же так много букав :(

russo
Offline
Зарегистрирован: 20.11.2014

brokly пишет:

Круто... Как вы это читаете и находите... Это же так много букав :(

Букав не много, 

есть проэкт со 8000 строк кода, правда на хай теке.

Опытный ардуинщик по названию темы уже знает несколько вариантов возможных ошибок. Для этого нужно хорошо знать компилятор.  

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

brokly,   да, жуть. Не полез бы в эту портянку, но я по  началу ардуино-изучения сам наступил на эти грабли, поэтому увидев у Т.С., что "зависает через минуту"  осталось только проверить в какие переменные он кладёт millis()

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Логично ! Круто!  Прямо поиском int в тексе ! И смотреть что он объявляет. Не читая текста.....

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

russo пишет:

Опытный ардуинщик по названию темы уже знает несколько вариантов возможных ошибок. Для этого нужно хорошо знать компилятор.  

Гм... Я и не знал, что можно классифицироваться ардуинщик или нет :)