дебажим гроб

std
Offline
Зарегистрирован: 05.01.2012

Моей главной ошибкой, с переходом на ArduinoISP и самопальные платы, был отказ от сериала. Теперь каждый раз, устанавливая плату в какую-нибудь автоматически хрюкающую роботизированную чушку, я понятия не имею, что там происходит...

Вместо эпиграфа

Сап, народ, и доброго времени суток тебе. Задача (алгоритм) такова: есть каменный ящик, типа гроб. На самом деле он из профилей, гипсокартона и снаружи только раскрашен под камень, но неважно. У него есть ручка, которую можно крутить, фоторезистор, в который можно светить, и сбоку лежат угли, которые можно раздувать. Угли можно считать кнопкой, там подпружиненная пластинка, сдуваемая воздухом из меха. Каких-то особенных исполнительных устройств нет, кроме движка, открывающего крышку. Он работает нормально. Всё остальное сообщается по радио, другим устройствам.

Единственная нерабочая вещь здесь - энкодер. Его код был взят из стандартной библиотеки encoder, оба провода поддерживают прерывания (d2, d3). Работало в примере, в котором был только он и 12 В лента (коммутируемая полевиком). Далее он как-то отошёл на второй план, и сейчас безнадёжно упущен момент, когда же он перестал работать. Внятно причину этого я назвать не могу, необходимо её найти. Мб кто-то знает, что может конфликтовать с ним.

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Encoder.h>

Encoder myEnc(3,2);
RF24 radio(8,9);
byte data[4];

const byte loga[64]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,16,18,22,25,28,29,30,33,36,39,42,46,49,53,56,60,64,68,72,
77,81,86,90,95,100,105,110,116,121,127,132,138,144,150,156,163,169,176,182,189,196,203,210,218,225,233,240,248,255};
const uint64_t pipes[2] = { 0xFFFFFFFF00LL, 0xFFFFFFFF01LL };

boolean flag_ir[3]={0,0,0},
        flag_match[4]={0,0,0,0},
        flag_open=0,
        flag_secret=0,
        flag_coals=0,
        blowflag=0;
byte counter[3]={0,0,0},
     countRecv=0,
     posFlag=0,
     oldFlag=0,
     light_next=0,
     light_lev=0,
     light_side_lev=0,
     coal_delta=0,
     coal_level=0;

long oldPosition=0;

unsigned long timestamp[7];

void setup(){ 
  pinMode(A5,INPUT);           // light sens
  pinMode(6,OUTPUT);           // light out

  pinMode(7,INPUT_PULLUP);     // coal sens
  pinMode(5,OUTPUT);           // coal light

  pinMode(0,OUTPUT);           // coffin door go
  pinMode(1,OUTPUT);           // reverse
  pinMode(4,INPUT_PULLUP);     // close endswitch
  pinMode(A3,INPUT_PULLUP);    // open endswitch

  pinMode(A2,INPUT);           // IR vases
  pinMode(A1,INPUT);
  pinMode(A0,INPUT);
  pinMode(A7,INPUT);
  pinMode(10,OUTPUT);           // LED strip
  timestamp[0]=millis();       // IR0    
  timestamp[1]=timestamp[0];   // IR1    
  timestamp[2]=timestamp[0];   // IR2    
  timestamp[3]=timestamp[0];   // IRMatch
  timestamp[4]=timestamp[0];   // encoder
  timestamp[5]=timestamp[0];   // last_radio
  timestamp[6]=timestamp[0];   // side light
  timestamp[7]=timestamp[0];   // coal report
  timestamp[8]=timestamp[0];   // coal up
  timestamp[9]=timestamp[0];   // coal down
  radio.begin();
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_MAX);
  radio.setChannel(1);
  radio.setRetries(15,15);
  radio.setPayloadSize(4);
  radio.openWritingPipe(pipes[1]);
  radio.openReadingPipe(1,pipes[0]);
  radio.startListening();

}
void loop(){
  long newPosition=myEnc.read(); 
  
// -- Encoder ---------------------------------------------
  if(newPosition!=oldPosition){
    oldPosition = newPosition;
    msgCentral(20,(byte) newPosition);
  }
//  updateFlag(3);
  if(posFlag==0 && oldPosition==240) updateFlag(1);  // #0: 3 to right
//  if(posFlag==1 && oldPosition>248)  resetFlag();    // overrotate 1
  if(posFlag==1 && oldPosition>260)  resetFlag();    // overrotate 1
  if(posFlag==1 && oldPosition==80)  updateFlag(2);  // #1: 2 to left
//  if(posFlag==2 && oldPosition<72)   resetFlag();    // overrotate 2
  if(posFlag==2 && oldPosition<60)   resetFlag();    // overrotate 2
  if(posFlag==2 && oldPosition==160) updateFlag(3);  // #2: 1 to right
//  if(posFlag==3 && oldPosition>180)  resetFlag();    // overrotate 3
  if(posFlag==3 && oldPosition>168)  resetFlag();    // overrotate 3
  if(posFlag==3 && oldPosition==0)   updateFlag(4);  // #3: 2 to left
//  if(posFlag==4 && oldPosition<-8)   resetFlag();    // overrotate 4
  if(posFlag==4 && oldPosition<-20)   resetFlag();    // overrotate 4
  if(posFlag==4 && oldPosition==160) updateFlag(5);  // #4: 2 to right
  if(posFlag==5) coffinOpen();
// -- Modify light level ----------------------------------
  if(millis()-timestamp[4]>=150 && light_lev<light_next){
    light_lev++;
    timestamp[4]=millis();
  }
  if(millis()-timestamp[4]>=50 && light_lev>light_next){
    light_lev--;
    timestamp[4]=millis();
  }
  analogWrite(10,light_lev);
//  analogWrite(10,loga[light_lev]);

// -- Enable ----------------------------------------------
  if(!digitalRead(A2)){
    if(!flag_match[0] && counter[0]>104 && counter[0]<115){   // 99k
      flag_match[0]=1;
      timestamp[3]=millis();
      msgCentral(1,1);  // coffin IR0
    }
    counter[0]=0;
    timestamp[0]=millis();
    flag_ir[0]=1;
  }
  if(!digitalRead(A1)){
    if(!flag_match[1] && counter[1]>65 && counter[1]<74){     // 66k
      flag_match[1]=1;
      timestamp[3]=millis();
      msgCentral(2,1);  // coffin IR1
    }
    counter[1]=0;
    timestamp[1]=millis();
    flag_ir[1]=1;
  }
  if(!digitalRead(A0)){
    if(!flag_match[2] && counter[2]>35 && counter[2]<44){     // 33k
      flag_match[2]=1;
      timestamp[3]=millis();
      msgCentral(3,1);  // coffin IR2
    }
    counter[2]=0;
    timestamp[2]=millis();
    flag_ir[2]=1;
  }
  if(!flag_match[3] && analogRead(A7)<100){
    flag_match[3]=1;
    msgCentral(4,1);  // coffin IR3
  }
// -- Counter ---------------------------------------------
  if(millis()-timestamp[0]>=100 && flag_ir[0]){
    counter[0]++;
    timestamp[0]=millis();
  }
  if(millis()-timestamp[1]>=100 && flag_ir[1]){
    counter[1]++;
    timestamp[1]=millis();
  }
  if(millis()-timestamp[2]>=100 && flag_ir[2]){
    counter[2]++;
    timestamp[2]=millis();
  }
// -- Disable ---------------------------------------------
  if(flag_match[0] && counter[0]>=115 && flag_ir[0]){
    counter[0]=0;
    flag_ir[0]=0;
    flag_match[0]=0;
    msgCentral(1,0);  // coffin IR0
  }  
  if(flag_match[1] && counter[1]>=74 && flag_ir[1]){
    counter[1]=0;
    flag_ir[1]=0;
    flag_match[1]=0;
    msgCentral(2,0);  // coffin IR1
  }  
  if(flag_match[2] && counter[2]>=44 && flag_ir[2]){
    counter[2]=0;
    flag_ir[2]=0;
    flag_match[2]=0;
    msgCentral(3,0);  // coffin IR2
  }  
  if(flag_match[3] && analogRead(A7)>=100){
    flag_match[3]=0;
    msgCentral(4,0);  // coffin IR3
  }
  if(flag_match[0] && flag_match[1] && flag_match[2] && flag_match[3] && !flag_open){
    flag_open=1;
    msgCentral(5,1);
  }

// -- Receiver --------------------------------------------
  if(radio.available()){
    radio.read(&data,4);
    if(data[0]==3 && data[1]==2  && millis()-timestamp[5]>=150){
      switch(data[2]){    // device code: 3
      case 1: coffinOpen(); break;
      case 2: coffinClose(); break;
      }
      timestamp[5]=millis();
    }
  }

// -- Side light ------------------------------------------
  if(analogRead(A5)>=180){
    if(light_side_lev<255 && millis()-timestamp[6]>=15){
      light_side_lev++;
      if(light_side_lev==255){
        flag_secret=1;
        msgCentral(6,1);  // secret open
      }
      timestamp[6]=millis();
    }
  }else if(analogRead(A5)<180){
    if(light_side_lev>0 && millis()-timestamp[6]>=7){
      light_side_lev--;
      timestamp[6]=millis();
    }
  }

// -- Coals heating ---------------------------------------
  if(millis()-timestamp[7]>=300 && !digitalRead(7)){
    timestamp[7]=millis();
    if(coal_delta<5) coal_delta++;
  }
  if(millis()-timestamp[7]>=700){
    coal_delta=0;
  }
  if(millis()-timestamp[8]>=100){
    if(coal_level<250) coal_level+=coal_delta;
    if(coal_level>1) coal_level-=1;
    timestamp[8]=millis();
  }
  if(coal_level>=250 && !flag_coals){
    msgCentral(7,1);    // coals heated, open
    flag_coals=1;
  }

// -- side/coal output ---------------------------------------
  analogWrite(6,coal_level);
  if(light_side_lev<5) analogWrite(5,0);
   else analogWrite(5,light_side_lev);
}

void resetFlag(){
  oldPosition=0;
  myEnc.write(0);
  posFlag=0;
  light_next=0;
}

void updateFlag(byte flag){
  posFlag=flag;
  switch(posFlag){
    case 1: light_next=4; break;
    case 2: light_next=12; break;
    case 3: light_next=39; break;
    case 4: light_next=86; break;
    case 5:
    case 6: light_next=255; break;
  }
}

void msgCentral(byte name,byte content){
  data[0]=255;
  data[1]=1;
  data[2]=name;
  data[3]=content;
  radio.stopListening();
  for(byte i=0;i<5;i++) radio.write(&data, 4);
  radio.startListening();
}

void coffinOpen(){
//  updateFlag(6); //DEBUG
  digitalWrite(1,0);
  digitalWrite(0,1);
  delay(500);
  digitalWrite(0,0);
}

void coffinClose(){
  digitalWrite(1,1);
  delay(100);
  digitalWrite(0,1);
  delay(500);
  digitalWrite(0,0);
  digitalWrite(1,0);
}

Комментарии скудны, так что задавайте вопросы. Времени в обрез, поэтому меня порадует любая помощь.

Вот что было выяснено:

1. При принудительном вызове updateFlag() в цикле, яркость повышается нормально, лента явно работает.

2. При поворотах энкодера она хаотично мигает, но иногда начинает разгораться до первой установки, как в случае updateFlag(1);

При некоторых условиях (они неизвестны, просто покрутили энкодер, в ту же сторону, или в другую сторону) лента перестаёт мигать вовсе.

3. Условие newPosition!=oldPosition не выполняется, с энкодера явно не приходит информация. Провода целы. Длина проводов 3 метра, три витых пары:

- питание (+5) и земля

- d2 и земля

- d3 и земля

Земли всех трёх пар соединены на плате энкодера (на стороне источника). Вроде всё по правилам. На плате собсно энкодер и подавитель дребезга на 7414. Осциллографа, чтобы посмотреть, что же там на самом деле, нет. Сериала нет. Если поставить в цикл вызов msgCentral(чтонибудь,(byte)newPosition) - приходят только нули, как если бы энкодер не крутился.

Вот что я думаю сделать, ибо дома, в тепличных условиях, плата энкодера (с короткими проводами да без лишнего в скетче) завелась с полпинка:

я поставлю ещё одну atmega8, она будет выдавать едницу нужной длины, чередующуюся коротким нулём, и по длительности единицы на основной плате понимать, куда откручен энкодер: три полных оборота вправо, два влево после этого и так далее. То есть, все чтения энкодера и функция updateFlag() переедут в отдельный контроллер.

Возможно, предложите ещё варианты.

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

std пишет:
Единственная нерабочая вещь здесь - энкодер. Его код был взят из стандартной библиотеки encoder, оба провода поддерживают прерывания (d2, d3). Работало в примере, в котором был только он и 12 В лента (коммутируемая полевиком). Далее он как-то отошёл на второй план, и сейчас безнадёжно упущен момент, когда же он перестал работать. Внятно причину этого я назвать не могу, необходимо её найти. Мб кто-то знает, что может конфликтовать с ним.

возможно потому, что отсутсвует флаг 

#define ENCODER_OPTIMIZE_INTERRUPTS

http://www.pjrc.com/teensy/td_libs_Encoder.html

  1. Best Performance: Both signals connect to interrupt pins.
  2. Good Performance: First signal connects to an interrupt pin, second to a non-interrupt pin.
  3. Low Performance: Both signals connect to non-interrupt pins, details below.
Клапауций 322
Offline
Зарегистрирован: 31.12.2015

и, вообще, кто запрещает использовать UART для отладки?

подключи по RX, TX атмега8 с HD44780 и пуляй в индикатор что тебе нужно

std
Offline
Зарегистрирован: 05.01.2012

К сожалению не помогло. Новая проблема, плата внезапно поломалась: теперь с энкодера приходят только две цифры: 0 и 1, ни больше ни меньше. Замена энкодера ничего не даёт.

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

std пишет:

К сожалению не помогло. Новая проблема, плата внезапно поломалась: теперь с энкодера приходят только две цифры: 0 и 1, ни больше ни меньше. Замена энкодера ничего не даёт.

подозреваю, что железо у тебя во время публикации первого поста было сломано.

std
Offline
Зарегистрирован: 05.01.2012

Окей all, всё что мне нужно, делается двумя ФД265 и компаратором LM393.

А энкодер послан нахер, бажное дилдо для цереброкоитальных утех. х█й его про███т как с ними работать.

karl2233
Offline
Зарегистрирован: 05.07.2015

std пишет:
 х█й его про███т как с ними работать.

ух ты какие значки... а  как эти прямоугольники получились?

про энкодер  -что мешает найти скетч с энкодером и попользовать необходимые куски?

std
Offline
Зарегистрирован: 05.01.2012

karl2233 пишет:
а  как эти прямоугольники получились?

Alt+219

karl2233 пишет:
что мешает найти скетч с энкодером и попользовать необходимые куски?

Да видимо дело не в скетче. Непонятно, или энкодеры китайские рассыпались (неизвестно как, 4 шт подряд?) или схемы глушения дребезга какие-то левые (там вроде тоже ошибиться негде - RC цепочка 220R+1uF и триггер Шмитта). Так или иначе, проверить нечем.