Blandat Arduino-skoj

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
pi314
Inlägg: 5829
Blev medlem: 23 oktober 2021, 19:22:37
Ort: Stockholm

Blandat Arduino-skoj

Inlägg av pi314 »

Blandat Arduino-skoj
Ibland vill jag dela kod-"snippets", små programdelar som kan vara användbara utan att vara fullständiga program. Ibland gör jag andra erfarenheter på "Arduino-området" som jag vill dela.

Eftersom jag inte hittat någon lämplig tråd för detta så startar jag en.

Jag börjar med en nyvunnen hårdvaruerfarenhet.

För lite sedan köpte jag tre Uni R3 från Az-Delivery. Häromdagen, när jag skulle ta dom sista två i bruk, så var en DOA (dead on arrival). Så här såg det ut när jag försökte ladda upp program till min Uno.
230807_AVRDude-error.png

Här finns 10 tips om hur felet ska åtgärdas.
https://www.programmingelectronics.com/ ... k500_recv/
Inget av dom tio förslagen hjälpte mig.

Jag swappade processor (ATmega328P, 28 pin DIL plastic, 0,1" delning i hållare). Fortfarande död och processorn fungerade på ett annat kort.

Då utsatte jag min Uno för okulärbesiktning och hittade detta.

230807_Uno-fel.jpg
En tennbrygga mellan pinnarna 7 och 8. Där ska kristallen vara. Värmde upp lödkolven, tog fram tennsugen och tog bort bryggan. Voila! Nu fungerar den!

/Pi
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Mindmapper
Inlägg: 6422
Blev medlem: 31 augusti 2006, 16:42:43
Ort: Jamtland

Re: Blandat Arduino-skoj

Inlägg av Mindmapper »

Känns ju inte som om AZ delivery och deras leverantör har någon effektivare kvalitetskontroll.
Rent sagt bedrövligt att sådant kan passera.
Användarvisningsbild
pi314
Inlägg: 5829
Blev medlem: 23 oktober 2021, 19:22:37
Ort: Stockholm

Re: Blandat Arduino-skoj

Inlägg av pi314 »

Mindmapper:

Ja, det är ju helt uppenbart att den inte testats före leverans. Jag borde ha meddelat leverantören (det är väl inte för sent ännu), men det kändes som om det var enklare att bara lösa problemet. Det var ju inte precis ett svårupptäckt eller svårlöst problem.

/Pi
Användarvisningsbild
pi314
Inlägg: 5829
Blev medlem: 23 oktober 2021, 19:22:37
Ort: Stockholm

Re: Blandat Arduino-skoj

Inlägg av pi314 »

Tidsstyrning med inbyggd klocka och interrupt
Om man vill hålla reda på hur lång tid som gått och delay() inte fungerar eftersom olika fördröjningar överlappar varandra så kan interrupt vara ett sätt att hålla reda på hur lång tid som passerat.
Det är lite krångligare att koda, men inte så mycket...

Kan t.ex. se ut så här.

Kod: Markera allt


//
// Simple example of time control with Arduino using interrupt.
//

boolean s10Event = false;    // On seconds==0, 10, 20, 30, 40, 50 event
boolean secondEvent = false; // On every second event
boolean e500msEvent = false; // On every 500 ms event
boolean firsttime=true;      // Controls code in loop() to be executed once.
int minutes = 0;
int seconds = 0 ;  
int seconds2 = 0 ;


//
// ***** setup *****
//
void setup(){
  Serial.begin(115200);      // Initialize serial communication
//
// Set up interrupt system, timer 1, for interrupt every 0.5 second.
// timer1 (16 bits) counts from 0 to 65535 and is used for the PWM control of pins 9 and 10.
// It is also used by the Servo.h library

  cli();                     // Disable all interrupts
//set timer1 interrupt at 1Hz
  TCCR1A = 0;                // set entire timer 1 TCCR1A register to 0
  TCCR1B = 0;                // same for timer 1 TCCR1B
  TCNT1  = 0;                // initialize timer 1 counter value to 0
// set compare match register for 2hz increments
  OCR1A = 31249;             // 16 Mhz/512 - 1 = (16*10^6) / (2*256) - 1 (must be <65536)
// As example: How to set 1 second/1 Hz interrupt.
//  OCR1A = 15624;           // 16 Mhz/1024 = (16*10^6) / (1*1024) - 1 (must be <65536)
  TCCR1B |= (1 << WGM12);    // turn on CTC mode
  TCCR1B |= (1 << CS12) | (0 << CS11) | (0 << CS10); // Set CS12 and CS10 bits for 256 prescaler
// As example: How to set prescaler for 1 second/1 Hz interrupt.
//  TCCR1B |= (1 << CS12) | (1 << CS10); // Set CS12 and CS10 bits for 1024 prescaler
  TIMSK1 |= (1 << OCIE1A);   // enable timer compare interrupt
  sei();                     // Enable interrupts

  Serial.println("");
  Serial.println("setup done.");

} // End setup


//
// Interrupt handler
//
ISR(TIMER1_COMPA_vect){ // Timer1 interrupt, 2Hz
  seconds2++;
  e500msEvent = true;
  if (seconds2<2) return;
  seconds2=0;
// Update second and minute counters.
  seconds++;
  if (seconds>59){
    seconds=0; minutes++;
    if (minutes>59) {minutes=0;}
  } // End of time count update

// Activate timer events
  if (10*floor(seconds/10)-seconds==0){s10Event = true;} // Every 10 second event
  secondEvent = true; // Every second event
} // End of interrupt handler


//
// ***** Main code, runs as infinite loop *****
//
void loop() {
  if (firsttime) {
// Do first time stuff.
// ...
    firsttime=false;
  }

// Handle every second event
  if (secondEvent){
    Serial.println("Handle every second event..."); 
    secondEvent = false;
  } // End secondEvent handler

//
// Do something every 10 seconds
//
  if (s10Event){
    Serial.println("Handle every ten second event..."); 
    s10Event = false;
  } // End s10Event handler

} // End of main loop().

/Pi
Användarvisningsbild
mankan
EF Sponsor
Inlägg: 908
Blev medlem: 18 juli 2015, 11:23:22
Ort: Linköping

Re: Blandat Arduino-skoj

Inlägg av mankan »

Det där kan man ju lösa med mha millis() utan att krångla med avbrott.
Användarvisningsbild
pi314
Inlägg: 5829
Blev medlem: 23 oktober 2021, 19:22:37
Ort: Stockholm

Re: Blandat Arduino-skoj

Inlägg av pi314 »

mankan:
I det där enkla, för att inte säga triviala, exemplet, ja.
Jag försökte hålla det enkelt för att illustrera just hur tidsstyrda interrupt fungerar och hanteras.
Jag har några exempel där jag inte kan lösa det på ett snyggt sätt med delay() eller millis().
Jag tänkte att jag ska återkomma senare med något sådant exempel.

Som Arnold sa:
I'll be back!
/Pi
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4695
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: Blandat Arduino-skoj

Inlägg av Swech »

Så som du kör interupt är riktigt bra. Blir bra kod

Denna hade jag nog implementerat med en egen räknare som räknar upp vid varje sekund och då den blir = 10 så
sätter du eventet och nollställer den

Kod: Markera allt

if (10*floor(seconds/10)-seconds==0){s10Event = true;}
Nu har du multiplikation och division i interupt rutinen vilket blir onödigt slött

Swech
Användarvisningsbild
pi314
Inlägg: 5829
Blev medlem: 23 oktober 2021, 19:22:37
Ort: Stockholm

Re: Blandat Arduino-skoj

Inlägg av pi314 »

Swech:

Tack för tips! :)

I praktiken har jag kanske fler liknande kontroller, för t.ex. var 5e, var 10e, var 60e etc. sekund.
Då kan det bli många onödiga multiplikationer och divisioner varje sekund.
Har jag högre tidsupplösning, t.ex. 100 ms eller 10 ms så är det ännu viktigare att ha en effektiv rutin som hanterar interrupt.

Jag ändrade till:

Kod: Markera allt


int seconds10=0; // 
...
  seconds10++:
  if (seconds10>9){ s10Event = true; seconds10=0; }

/Pi
Användarvisningsbild
pi314
Inlägg: 5829
Blev medlem: 23 oktober 2021, 19:22:37
Ort: Stockholm

Re: Blandat Arduino-skoj

Inlägg av pi314 »

Användning av interruptstyrd timer
Jag ser några tillämpningar framför mig där jag har användning för att hålla reda på passerad tid för några olika "parallella processer" och avläsning av några olika givare med fördefinierade tidsintervall.

En riktigt enkel tillämpning aktualiserades av trasiga eller otillförlitliga äggklockor.

Först hade jag en som då och då stannade. Jag skaffade en till. Efter ett tag slutade den ringa. Då skaffade jag en tredje. Den ringer inte alltid. Då föddes idén att göra en egen.

Jag håller reda på tiden med interrupt och kod liknande den ovan.

Jag är inte helt nöjd med användargränssnittet, men det fungerar.

Den har två tryckknappar och en OLED-display.

Så här ser displayen ut.
Kitchentimers.jpg
Den översta raden är en klocka.
-- anger att ingen inställningsfunktion är aktiverad. Med knapp 1 cyklas förbi HH, MM, SS, H1, M1, H2, M2, H3, M3 för att ställa klockan eller någon av dom tre "timersarna". Inställningen sker sedan med knapp 2. Timersarna kan ställas på upp till 99 timmar och 59 minuter. Jag har plockat fram en liten högtalare för larm, men inte kopplat in den ännu.

/Pi
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
pi314
Inlägg: 5829
Blev medlem: 23 oktober 2021, 19:22:37
Ort: Stockholm

Re: Blandat Arduino-skoj

Inlägg av pi314 »

Behövde en signal till äggklockan.
Testade denna.
Den kan driva en liten högtalare direkt kopplad till utgång pinne 8, men nivån är lite låg och jag ska förstärka den lite.
Skulle tro att det räcker med en transistor för att få upp nivån lite.

Kod: Markera allt

/*
  sound2speaker.ino

  Plays a sound.
  circuit:
  - 8 ohm speaker on digital pin 8. Perhaps an amplifier.
  2023-08-17 bos - Created
*/

#define soundpin 8
#define pitchmin 600
#define pitchmax 1200
#define raisedelay 8
#define raisefast 1
#define pitchmaxtime 1000 // 1000 ms = 1 second

void setup() {
  Serial.begin(115200);
  alarm(); // Once...
  Serial.println("Start of sound signal.");
}

void alarm(){  
  for (int i = 1; i < 4; i++) {
  
// Loop over the tones.
// Raising pitch, from pitchmin Hz to pitchmax Hz - Slow
    for (int pitch = pitchmin; pitch <= pitchmax; pitch=pitch+2) {
      tone(soundpin, pitch, 100000);
      delay(raisedelay);
    } // End for pitch

    for (int j = 1; j < 6; j++) {
// Raising pitch, from pitchmin Hz to pitchmax Hz - Faster
      for (int pitch = pitchmin; pitch <= pitchmax; pitch=pitch+2) {
        tone(soundpin, pitch, 100000);
        delay(raisefast);
      } // End for pitch
    } // End for j

// Constant pitch, pitchmax Hz
//    for (int pitch = pitchmin; pitch <= pitchmax; pitch=pitch+5) {
      tone(soundpin, pitchmax, 100000);
      delay(pitchmaxtime);
//    } // End for pitch

// Pitch going down, from pitchmax Hz to pitchmin Hz.
    for (int pitch = pitchmax; pitch >= pitchmin; pitch=pitch-5) {
      tone(soundpin, pitch, 100000);
      delay(16);
    } // End for tone
  } // End for i

// Pitch going down, from pitchmin-5 Hz to 60 Hz.
    for (int pitch = pitchmin-5; pitch >= 50; pitch=pitch-5) {
      tone(soundpin, pitch, 100000);
      delay(40);
    } // End for tone

    noTone(soundpin);
    Serial.println("Sound signal done!");
} // End alarm


void loop() {

//  alarm(); // Forever

}
/Pi
Användarvisningsbild
pi314
Inlägg: 5829
Blev medlem: 23 oktober 2021, 19:22:37
Ort: Stockholm

Re: Blandat Arduino-skoj

Inlägg av pi314 »

Signalen ovan låter ungefär så här.
police-siren.mp3
/Pi
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
agehall
Inlägg: 427
Blev medlem: 12 augusti 2020, 19:27:54

Re: Blandat Arduino-skoj

Inlägg av agehall »

Jag saknar

Kod: Markera allt

volatile
på alla variabler som delas mellan ISR och övrig kod.
Användarvisningsbild
pi314
Inlägg: 5829
Blev medlem: 23 oktober 2021, 19:22:37
Ort: Stockholm

Re: Blandat Arduino-skoj

Inlägg av pi314 »

agehall:
Tack för påminnelse!
Kul att se att någon tittar på mina "snippets"!

Här är en uppdaterad version av det enkla "tidsstyrda" interrupt-programmet.
Där globala variabler som ändras i interrupthanteringsrutinen (ISR) är volatila.

Kod: Markera allt

//
// Simple example of time control with Arduino using interrupt
//
// 2023-08-15 pi Initial version.
// 2023-08-18 pi Made global variables modified in ISR volatile.

volatile boolean s10Event = false;     // On seconds==0, 10, 20, 30, 40, 50 event
volatile int seconds10=0;              // Counter
volatile boolean secondEvent = false;  // On every second event
volatile boolean e500msEvent = false;  // On every 500 ms event
boolean firsttime=true;       // Controls code in loop() to be executed once.
volatile int minutes = 0;
volatile int seconds = 0 ;  
volatile int seconds2 = 0 ;


//
// ***** setup *****
//
void setup(){
  Serial.begin(115200);      // Initialize serial communication
//
// Set up interrupt system, timer 1, for interrupt every 0.5 second.
// timer1 (16 bits) counts from 0 to 65535 and is used for the PWM control of pins 9 and 10.
// It is also used by the Servo.h library

  cli();                     // Disable all interrupts
//set timer1 interrupt at 1Hz
  TCCR1A = 0;                // set entire timer 1 TCCR1A register to 0
  TCCR1B = 0;                // same for timer 1 TCCR1B
  TCNT1  = 0;                // initialize timer 1 counter value to 0
// set compare match register for 2hz increments
  OCR1A = 31249;             // 16 Mhz/512 - 1 = (16*10^6) / (2*256) - 1 (must be <65536)
// As example: How to set 1 second/1 Hz interrupt.
//  OCR1A = 15624;           // 16 Mhz/1024 = (16*10^6) / (1*1024) - 1 (must be <65536)
  TCCR1B |= (1 << WGM12);    // turn on CTC mode
  TCCR1B |= (1 << CS12) | (0 << CS11) | (0 << CS10); // Set CS12 and CS10 bits for 256 prescaler
// As example: How to set prescaler for 1 second/1 Hz interrupt.
//  TCCR1B |= (1 << CS12) | (1 << CS10); // Set CS12 and CS10 bits for 1024 prescaler
  TIMSK1 |= (1 << OCIE1A);   // enable timer compare interrupt
  sei();                     // Enable interrupts

  Serial.println("");
  Serial.println("setup done.");

} // End setup


//
// Interrupt service routine (ISR)
//
ISR(TIMER1_COMPA_vect){ // Timer1 interrupt, 2Hz
  seconds2++;
  e500msEvent = true;
  if (seconds2<2) return;
  seconds2=0;
// Update second and minute counters.
  seconds++;
  if (seconds>59){
    seconds=0; minutes++;
    if (minutes>59) {minutes=0;}
  } // End of time count update

// Activate timer events
  seconds10++;
  if (seconds10>9){ s10Event = true; seconds10=0; } // Every 10 second event
  secondEvent = true; // Every second event
} // End of interrupt handler


//
// ***** Main code, runs as infinite loop *****
//
void loop() {
  if (firsttime) {
// Do first time stuff.
// ...
    firsttime=false;
  }

// Handle every second event
  if (secondEvent){
    Serial.println("Handle every second event..."); 
    secondEvent = false;
  } // End secondEvent handler

//
// Do something every 10 seconds
//
  if (s10Event){
    Serial.println("Handle every ten second event..."); 
    s10Event = false;
  } // End s10Event handler

} // End of main loop().
/Pi
BJ
Inlägg: 8303
Blev medlem: 11 april 2007, 08:14:53
Ort: En_stad

Vad är volatile, och när behöver man använda det?

Inlägg av BJ »

Vad är volatile, och när behöver man använda det?
agehall skrev: 18 augusti 2023, 07:03:37 Jag saknar

Kod: Markera allt

volatile
på alla variabler som delas mellan ISR och övrig kod.

Varför måste dom vara volatile? Räcker det inte med att dom är globala?
Jag har programmerat en del Pic i assembler med globala variabler.
Där finns inte volatile.
Varför finns det i c, och vad gör det för något?
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43178
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Vad är volatile, och när behöver man använda det?

Inlägg av sodjan »

Volatile talar om för kompilatorn att "denna variabel kan ändras på andra sätt än vad man kan tro genom att enbart titta på koden".
Global har ingenting med det att göra...

Två typiska fall är där en interrupt och huvudkoden och där ett register (mappad till en variabel) kan ändras av hårdvaran.

I assembler så har du inte någon kompilator med en optimerare. Om något är "volatile" så får du tänka på det själv i koden.
Skriv svar