Sari la conținut
ELFORUM - Forumul electronistilor

Arduino IDE - blocaj uC


Postări Recomandate

Vreau păreri și opinii generale despre un anumit comportament al uC-ului fie el attiny85, atmega32, atmega8, esp8266 , orice.. si nu contează ce cod dar ne referim la coduri funcționale. 

 

dupa X timp, controlerul fie se resetează fie rămâne blocat. când se întâmplă asta? pai exact asta încerc sa aflu. 

 

am încercat o chestie înainte sa postez. in setup citim un buton pentru iesire dintr-un while, iar în loop facem calcule fara sens doar sa fie uC ocupat. am folosit si millis(). dacă cumva incearca sa-si dea Reset nu va trece neobservat va rămâne in while-ul din setup. 

 

a trecut pana la primul blocaj 26 de zile. 

al doilea blocaj a fost după alte 8 zile. 

 

tensiunea a fost cu un acumulator tampon ca sa evitam fluctuațiile sau sa rămână fără tensiune. 

 

revenind. voi experimentați astfel de situații? 

e ceva legat de Atmel? 

e ceva legat de Arduino IDE? 

Editat de Gilbert Sparios
Link spre comentariu

se blocheaza din cauza rutinelor C si stiu pe multi care au patit-o. Din cauza asta nu mai folosesc C demult si am montaje cu 8051, atmega32 sau atmega2560 care merg de ani buni incontinuu (fara sa folosesc watchdog-ul). Dealtfel, pentru cei ce folosesc C, watchdog-ul e cam singura solutie pentru a evita blocarea microcontrolerelor (din cauza asta a si fost introdus). Alta solutie ar fi dezasamblarea fisierelor hex si foarte multa bataie de cap.

Editat de cimitavita
Link spre comentariu

Teoria zice ca, din cauza de impedanta de intrare mare, intrarile CMOS nu se lasa in aer, ca pot genera efecte neasteptate (cel mai pasnic fiind consumul sporit). Primul link returnat de gogu la fraza de cautare "cmos unused inputs" e https://www.electronicdesign.com/technologies/boards/article/21765936/save-power-by-managing-unused-cmos-io-pins, da' poti sa mai citesti si altele.

Nu stiu exact cum e la ATMega, da' la picuri dupa reset pinii sunt facuti intrari.

Ca sa eviti surprizele, ori faci pinii nefolositi iesiri, ori activezi pullup-urile (daca au).

Link spre comentariu

Cel mai des blocajele survin datorita variabile prost definite/initializate/folosite asa cum spunea Liviu M.

 

La ATMEGA, dupa reset, toti pinii sunt intrari cu pull-up activat, adica toti sunt pe 1 logic. Nu e nevoie ca pinii nefolositi si ramasi ca intrari sa fie pusi la masa. S-ar consuma curent inutil.

Prin pull-up sunt legati la Vcc prin rezistente interne de 10K. Pull-up poate fi activat/dezactivat la fiecare pin in parte. 

Daca se dezactiveaza pull-up general, pinii nefolositi ar trebui facuti iesiri sau lasati tot intrari dar legati la Vcc si nu la masa.

La ATMEGA, in cazul folosirii convertorului AD, la pinii folositi ca intrari analogice, pull-up trebuie dezactivat altfel ramane ramane legat la Vcc prin rezistenta interna de 10K. Rezistenta la intrarile ADC depinde de frecventa aleasa pentru prescalerul ADC si este cuprinsa intre 10K si 100M.

Editat de cimitavita
Link spre comentariu

Din foaia de catalog a lui ATMega328:

Citat

The DDxn bit in the DDRx register selects the direction of this pin. If DDxn is written logic one, Pxn is configured as an output pin. If DDxn is written logic zero, Pxn is configured as an input pin. If PORTxn is written logic one when the pin is configured as an input pin, the pull-up resistor is activated. To switch the pull-up resistor off, PORTxn has to be written logic zero or the pin has to be configured as an output pin. The port pins aretri-stated when reset condition becomes active, even if no clocks are running.If PORTxn is written logic one when the pin is configured as an output pin, the port pin is driven high (one). If PORTxn is written logic zero when the pin is configured as an output pin, the port pin is driven low (zero).

 

13.4.2   PORTB – The Port B Data Register
Bit                    7          6        5         4          3       2         1       0
0x05 (0x25)          PORTB7    PORTB6    PORTB5    PORTB4    PORTB3    PORTB2    PORTB1    PORTB0 PORTB
Read/Write             R/W       R/W      R/W       R/W       R/W        R/W       R/W   R/W
Initial Value           0         0        0         0         0         0         0       0

 

13.4.3   DDRB – The Port B Data Direction Register
Bit                    7          6        5         4          3       2         1       0
0x05 (0x25)           DDB7       DDB6     DDB5      DDB4      DDB3     DDB2        DDB1   DDB0  DDRB
Read/Write             R/W       R/W      R/W       R/W       R/W        R/W       R/W   R/W
Initial Value           0         0        0         0         0         0         0       0

Cu alte cuvinte, dupa reset (initial value) pinii sunt intrari fara pullup. Sau citesc eu aiurea?

 

Editat de Liviu M
Link spre comentariu

Asa cum am spus in prima postare, nu ne referim la un anumit soft. Este o generalitate, dar nu fara exceptii si-am observat asta si pe alte uC-uri de exemplu masina de tuns personala, un Philips care a trebuit sa-l desfac de urgenta pentru ca s-a pornit de nebun in dulap si nu s-a lasat pana nu i-am dat reset la uC-ul lor.. sau alte device-uri. am si aplicatii destul de complexe care nu au inghetat niciodata in 3 ani. de fapt majoritatea, dar nici numarul celor care o patesc nu e chiar neglijabil. daca mi se intampla doar mie e clar, sunt eu de vina, si sper sa fie asa.

 

o sa postez codul pe care l-am folosit in test, dar va rog sa tine-ti cont, ca nu este vorba de doar acest cod Test. totusi, daca e ceva gresit in cod care vi se pare a fi suspect...

 

@nico_2010 tensiunea de alimentare este de 4.98V, capacitor de 100nF pe pinii uC-ului plus un 470uF. Tensiunea o ia dintr-un acumulator de 12V care este pus pe incarcare dar e de incredere incarcatorul. Mai departe este un 22uF16V, 1 x 100nF (stiu ca sunt degeaba dupa acumulator dar mna..) apoi LM317 setat pe tensiunea de mai sus,  cu radiator fara numar, urmat pe iesire de 2 x 100nF si 47uF. 

A trebuit sa fac cu o baterie tampon pentru ca stiam ca trebuie sa mearga mult...pana sa apara o problema. 

 

/*
PROGRAM TESTARE
 */

#include <avr/wdt.h>

#define INPUT_BUTTON	6	// push button but NormalClose (NC)
#define LED_PIN	13
uint8_t PINuC[17] = {
  2,3,4,5,6,7,8,9,10,11,12,A0,A1,A2,A3,A4,A5};


#define LED_PULSE_FAST	100UL
#define LED_PULSE_SLOW	500UL

// LOCAL RENAME
#define FAST	1
#define SLOW	0

uint32_t cMs = 0;
uint32_t lastPulseLed = 0;

// fake variables
float a = 0.0;
float b = 0.0;
float c = 0.0;


void setup(){
  for (int i=0;i<sizeof(PINuC);i++) pinMode(i,INPUT_PULLUP);
  pinMode(LED_PIN,OUTPUT);
  uint8_t btnState = 0;

  while (!btnState) {
    btnState = digitalRead(INPUT_BUTTON);
    cMs = millis();
    blink(FAST);
  } //end.while
  wdt_enable (WDTO_2S);
}

void loop(){
  wdt_reset ();
  cMs = millis();
  blink(SLOW);
  test_procedure();
}

/*PROCEDURES*/
void test_procedure() {
  static float d = 0.0, e = 0.0, f = 0.0;  
  a = PI;
  b = random(10.18,37.65);
  c=pow(b,2)*a;
  d = c;
  c=pow(b,2)*a;
  e = c;
  c=pow(b,2)*a;
  f = c;
  if (((d+e+f)) != (pow(b,2)*a)*3.0) {
    digitalWrite(LED_PIN,1);
    while(1){
      wdt_reset ();
      delay(10UL);
    }
  }
}

void blink(uint8_t mode){
  switch (mode) {
  case SLOW:
    if ((cMs-lastPulseLed) >= LED_PULSE_SLOW) {
      lastPulseLed = cMs;
      digitalWrite(LED_PIN,!digitalRead(LED_PIN));
    }
    break;

  case FAST:
    if ((cMs-lastPulseLed) >= LED_PULSE_FAST) {
      lastPulseLed = cMs;
      digitalWrite(LED_PIN,!digitalRead(LED_PIN));
    }
    break;

  default:
    digitalWrite(LED_PIN,0);
    while(1){
      wdt_reset ();
      delay(10UL);
    }      
    break;
  } // end.case
}

 

 

L.E: vin cu o alta intrebare legata de uint32_t. alocat in variabila cMs sau alte variabile unsigned long, va avea o maxima de (2^32 - 1) practic aproximativ 50 zile. Dupa care millis() va returna zero. Pe undeva nu ar trebuii sa fie mare problema va sari un pic peste ceva timpi. Cel putin aparent. Poate ar trebuii 

if ((cMs-lastPulseLed) >= LED_PULSE_SLOW)

sa devina mereu ?:

if (((cMs-lastPulseLed) >= LED_PULSE_SLOW) && (cMs>lastPulseLed))

sau pur si simplu o rutina care verifica pe millis() cand acesta este 0..50 sau mai putin de 50 sa reseteze si variabilele care au legatura cu millis() ?

if (cMs  < 50) {
	lastPulseLed = cMs;
    //....
}

 

Editat de Gilbert Sparios
Link spre comentariu
Acum 9 ore, mihaicozac a spus:

Posibil ca millis() să fie de vină.

Pe de altă parte, am o automatizare de încălzire centrală care funcţionează cu lunile fără blocaje. Nu foloseşte millis() nicăieri.

 

te intreb si eu doar. cum faci la o automatizare de exemplu sa rulezi supravegherea adica..programul in sine, dar sa si afisezi ? scri la fiecare loop() pe display o zona anume, apoi la fiecare loop() adaugi un delay(xx) iar citirile de butoane le faci intreruperi sau cum ?

eu as prefera millis() si sa nu ma ating de timer0 in general..

 

intreruperile le folosesc daca am de citit altceva decat butoane. de exemplu un knob, sau daca citim o frecventa, dar pentru un buton..nu mai folosesc intreruperi. doar eu folosesc millis() ?...

 

 

@Liviu M nu cred ca citesti gresit. in orice caz dupa reset uC care are bootloader compatibil Arduino IDE vine cu toate intrarile pe INPUT. fara PULLUP. La atmega328 posibil ca PB5 sa vina cu OUTPUT pentru Led din bootloader dar in rest totul e INPUT

 

asa si era sa uit cel mai important aspect in dezbaterea asta. ca isi da reset e cel mai fericit caz. dar sunt cazuri când rămâne blocat pur si simplu nu face nimic. aparent e mort pana la reset. 

 

eu tind sa cred ca problema este totuși in compilator care transforma C in hex. sper sa vorbesc prostii.. 

sau.. poate unele quart-uri nu au calitate. cu toate ca de pe tme le cumpăr. si apropo de quart

am o plăcută de uno care porneste usb pe baza de bricheta sau deget cald, aplicat foc pe quart-ul lui atmega16U2, scurt. ciudat nu? mai ales ca nu e vreo lipitura rece. 

Editat de Gilbert Sparios
Link spre comentariu

scuze, am gresit.

La pornire PUD = 0, DDRx=00h, PORTx =00x si PINx=00h. Pentru ca pull-ul sa fie activat ar fi trebuit ca PORTx=FFh. Singura exceptie sunt bitii folositi de JTAG. Problema se rezolva inchizand JTAG din fuse.

Arduino care porneste pe baza de deget cald are probleme cu cuartul, condesatoarele de la cuart sau chiar oscilatorul microcontrolerului.

 

 

 

Link spre comentariu
Acum 8 ore, Gilbert Sparios a spus:

eu as prefera millis() si sa nu ma ating de timer0 in general..

 

intreruperile le folosesc daca am de citit altceva decat butoane. de exemplu un knob, sau daca citim o frecventa, dar pentru un buton..nu mai folosesc intreruperi. doar eu folosesc millis() ?...

 

Mi se pare gresita abordarea ta. Eu la PIC-uri evit cat pot sa folosesc delay-uri in aplicatiile pe care le scriu, doar intreruperi, si niciodata nu mi se blocheaza MCU chiar daca functioneaza nonstop (de ex ceasurile se opresc doar cand se ia curentul). Si nici quart-uri nu folosesc... doar in cazul cand trebuie sa am un clock foarte precis. In schimb sunt atent la definirea variabilelor, si la initierea registrilor.

L.E.

Si bineinteles proiectarea corecta a cablajului: trasee pentru intrari cat mai scurte, evitarea routarii acestora pe langa traseele de forta, decuplarea alimentarii MCU cat mai aproape de pinii corespunzatori cu un C de 100n, eventual in paralel cu unul de 10u daca mediul sau alimentarea are zgomot.

Editat de Kreator
Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum
×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări