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

Re: Blandat Arduino-skoj

Inlägg av pi314 »

När man skapar en ny "skiss" i Arduino så ser den ut så här.

Kod: Markera allt

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}

Tanken är väl att engångskod/initialisering ska ligga i setup(). Den koden exekveras när man startar och när man startar om. En gång.

loop() är en oändlig loop. Den koden upprepas.
Procedurer eller funktioner utanför setup() och loop() kan anropas från båda.

Med interrupt blir det lite annorlunda.
Typiskt tror jag att det ser ut ungefär så här.
Man definierar vilka interrupt man ska använda i setup().
Interrupthanteringen sker i Interrupt service routine (ISR).

Som jag ser det öppnar interrupt möjligheter som kan vara svåra att uppnå utan interrupt.

Här är några exempel.
1. Man kan låta en inbyggd timer orsaka interrupt.
2. Man kan låta en yttre enhet orsaka interrupt.
3. Man kan ha givare som ska hanteras med avläsning t.ex. 0,5 sekunder efter att dom adresseras.
4. Man kan ha flera givare som ska avläsas med vissa, men olika, tidsintervall.
5. Man har något som ska styras på ett sätt som beror av t.ex. förlöpt tid.
6. Man har en process som ska styras, beroende på givarsignaler och passerad tid.

Det är när man börjar kombinare flera av alternativen ovan som det börjar bli intressant, IMO.

Jag ser en tidsstyrd mini-scheduler, som i exemplet ovan, som en byggsten som man kan använda för att göra något "större".

/Pi
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43178
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Blandat Arduino-skoj

Inlägg av sodjan »

Ah, OK. Så då sker det anrop till setup() från någon init rutin som man inte skriver själv utan som länkas in i projektet då man "bygger" det.
Aja, jag har aldrig gjort något med Arduino och ska väl hålla mig borta från de diskussionerna... :-)

Dina punkter kring interrupt är väl inget att orda om, det är ju grundläggande saker.
Men visst, det gäller att planera sina ISR'er bra om man har flera olika interrupt källor.
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 »

Eller ett annat väldigt vanligt exempel.

Kod: Markera allt

loop
  var1 = PORTA
  gör något med var1...
end-loop
Detta kan en optimerare ändra till:

Kod: Markera allt

var1 = PORTA
loop
  gör något med var1...
end-loop
D.v.s. att PORTA bara läses en gång och inte varje runda i loopen.
Volatile gör att den optimeringen inte görs.
Nerre
Inlägg: 26709
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

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

Inlägg av Nerre »

Ja, eller detta:

Kod: Markera allt

var=1
(diverse kod i väntan på att var ska ändras)
if var==0 (gör nåt)
Optimeras bort helt, eftersom kompilatorn tycker att "var är alltid 1, så if-satsen kommer aldrig köras, och var används bara i if-satsen så den behövs inte alls".
BJ
Inlägg: 8303
Blev medlem: 11 april 2007, 08:14:53
Ort: En_stad

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

Inlägg av BJ »

Okej. Det här visste inte jag. Tack. :tumupp:
Användarvisningsbild
pi314
Inlägg: 5829
Blev medlem: 23 oktober 2021, 19:22:37
Ort: Stockholm

Re: Blandat Arduino-skoj

Inlägg av pi314 »

Visst är detta med tidsstyrda interrupt grundläggande och självklart.

Samtidigt är det inte ovanligt att Arduino-exempel som publiceras är "sekventiella". Exempelvis en givare och en display. Läs av givaren och presentera resultatet på displayen och upprepa i all evighet. Att bygga vidare på den metoden fungerar i många sammanhang,

Här är ett exempel på en tillämpning som jag tänkte lösa med interrupt och timer.

Jag har en effektmätare som baseras på blink på elmätaren. I min elmätare har jag 1000 blink per kWh. Vid 50 watt, som är ungefär min "viloförbrukning" här, är det 72 sekunder mellan blinken. Om jag har spisen eller ugnen på med 2 kW och stänger av spisen eller ugnen så kan det ta upp till 72 sekunder innan visningen går från 2000 watt till 50 watt. Då var min tanke att ha koll på tiden från senaste blink och jämföra. Om tiden då t.ex. är 10% mer än motsvarande vad som visas så kan jag sänka visad effekt. Då kan man se den trappa ner från 2000 watt till 50 watt, i stället för att titta på 2000 watt i 72 sekunder och börja undra om något är fel.

/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 »

Ytterligare en grej att tänka på angående volatile är om man har kod:

Kod: Markera allt

struct foo {
  int a;
  int b;
}

void update_foo(foo *f)
{
   f->a = 10;
   f->b = 0;
}
så kan kompilatorn fritt ändra ordningen på tilldelningen vilket kan ställa till det om vissa kombinationer av värden indikerar ett visst tillstånd när man läser en foo. BTDT!
MiaM
Inlägg: 9990
Blev medlem: 6 maj 2009, 22:19:19

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

Inlägg av MiaM »

Findecanor skrev: 18 augusti 2023, 11:25:52Jag har hört någonstans att "volatile" skulle ha kommit till för hårdvaruregisters skull. Det finns mycket hårdvara som sätter igång saker när man skriver till ett register, även om man skriver samma värde som tidigare, så därför skulle kompilatorn vara förbjuden att göra detta.
Sidospår: Det verkar finnas något av en konvention att detta är något som händer i maskiner med vissa processorer, medan med andra processorer händer det inte. Till exemple så kan 6502 och om jag minns rätt även 6800 inte berätta för omvärlden att den inte har för avsikt att läsa/skriva från/till minnet under en viss cykel då den gör saker internt, så därför genererar den extra dummyläscykler på om jag minns rätt adressen som nyss lästes eller skrevs. (Dessa har minnesmappad I/O). Därmed är det dåligt att ha hårdvara som reagerar enbart på minnesaccess. Det finns visserligen I/O-kretsar som rensar infon om vad som genererat interrupt när visst register lästs, men för att detta ska bli ett problem så måste man i princip råka generera en interrupt precis när man läst detta register och dessutom dumt nog använda nån instruktion som genererar dummycykler. Fritt ur minnet så tror jag att en ren inläsning från minne på fast adress till register inte genererar sådana cykler, utan det är väl mer de tillkrånglat indirekta adresseringarna som får processorn att generera en hel del dummycykler.
Nerre skrev: 18 augusti 2023, 15:19:35Ja, eller detta:

Kod: Markera allt

var=1
(diverse kod i väntan på att var ska ändras)
if var==0 (gör nåt)
Optimeras bort helt, eftersom kompilatorn tycker att "var är alltid 1, så if-satsen kommer aldrig köras, och var används bara i if-satsen så den behövs inte alls".
Ja, och dessutom så ifall var inte används senare så optimeras även var=1 bort. :)
Nerre
Inlägg: 26709
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Blandat Arduino-skoj

Inlägg av Nerre »

Ja jag skrev ju det? :)
och var används bara i if-satsen så den behövs inte alls
Så hela koden försvinner alltså (utom då kanske (diverse kod)).

Det är ganska vanligt just att folk som inte har koll på detta undrar varför kod "försvinner".

Kompilatorns optimering kan vara rätt brutal. När jag började leka lite med AVR för en massa år sen ville jag jämföra C med assembler för ett kort program och provade olika nivåer av optimering.

Jag tror att mitt assemblerprogram var typ 7-8 rader, den o-optimerade C-koden blev säkert 30 rader (men säkert 10 av de raderna var initiering, t.ex. satte kompilatorn ett register till 0 för att använda för att nolla variabler som ligger i RAM, jag misstänker att det inte går att skriva konstanter direkt till RAM och därför används den lösningen).

På första försöket med högsta optimering fattade jag knappt assemblerkoden :) Men lyckades till slut (genom att både justera min assembler-kod och C-koden) få kompilatorn att generera nåt som såg likadant ut som min assemblerkod (dock la kompilatorn såklart fortfarande till en massa initiering).
BJ
Inlägg: 8303
Blev medlem: 11 april 2007, 08:14:53
Ort: En_stad

Re: Blandat Arduino-skoj

Inlägg av BJ »

Jag har också jämfört lite.
Något som var ganska enkelt att göra i assembler på Pic,
nämligen kopiera lite bitar mellan register, med
"bit test file" och "bit set file," gjorde c-kompilatorn
något långt och krångligt av med xor och grejer,
som var längre än om det hade varit gjort i assembler direkt.
Användarvisningsbild
pi314
Inlägg: 5829
Blev medlem: 23 oktober 2021, 19:22:37
Ort: Stockholm

Re: Blandat Arduino-skoj

Inlägg av pi314 »

Traktens nördigaste köksklocka
230819_kitchen_clock_www.jpg
Den har nått status "användbar" men behöver förfinas.
Den har två funktioner. En klocka och tre timers. Timersarna kan sättas i steg om en minut upp till 99 timmar och 59 minuter.
Min respektive gillar långkok och ställer då äggklockan på en timme flera gånger. Det behövs inte på denna.
För att klockan, som baseras på den inbyggda kristallklockan, ska gå rätt, så behöver den justeras. Det gör jag nu genom att mäta hur mycket den går fel på ett dygn. Sedan justeras fel över 24 sekunder varje timme och det som är kvar varje dygn. Jag har inte långtidsmätt, men gissar att den går mindre fel än någon minut, per månad, efter justering. Om man har ungefär konstant temperatur i köket. En del Arduinos har en keramisk klockbas i stället för kristall. Dom lämpar sig inte som bas för en klocka. Det finns externa klockor att köpa till Arduino, som kan fungera om man har keramisk internklocka.

Hårdvara
– En Arduino Uno (eller klon).
– En OLED-display.
– En liten högtalare. Jag använder en gammal datorhögtalare, Fuji, 8Ω, 0,4 watt.
– Två små tryckströmbrytare för inställning av tid och timers.

Kod
Koden har tidsstyrt interrupt med 2 HZ, som i exemplet ovan i tråden, som bas. Jag har ett eget bibliotek som driver OLED-displayen.

Nuvarande användargränssnitt
Klockan justeras för att gå rätt med en konstant i koden. Kräver omkompilering efter justering.
Inställningar baseras på knapptryck. Knapp ett väjer mode och knapp två stegar fram till önskat värde. Dom moder som finns nu är --, HH, MM, SS, H1, M1, H2, M2, H3 och M3
Klockan ställs med HH, MM och SS till rätt tid.
Timersarna ställs med timmar (H1, H2 och H3) och minuter (M1, M2 och M3).
Ljudsignalen inleds och avslutas med 1-3 pip för att ange vilken timer det är som larmar.

Användargränssnittet behöver förbättras
Jag skulle uppskatta förslag till förbättringar. Här är några tankar som jag har.
– Rucka med knapparna i stället för med omkompilering.
– Ändra ordningen i menyn. Kanske till --, M1, M2, M3, H1, H2, H3, HH, MM, SS, A+ och A- där A är för "adjust", för att rucka klockan. Sekunder per dygn. Timer mer än 59 minuter torde vara ovanlig i det svenska köket.
– Menyn stannar nu på valt alternativ. Kanske borde det återgå till "--" efter en minuts inaktivitet?

Efter några förbättringar kan det kanske bli ett miniprojekt?

Utvecklingsmöjligheter
Om man t.ex. kopplar in ett eller flera solid-state-reläer eller vanliga reläer så kan man tidsstyra elektriska apparater. Som kaffebryggare eller belysning. Bevattning. Men då kanske man vill ha en fuktsensor också? Tidsstyrd uppvärmning. Sänk innetemperaturen en grad eller två då elen är som dyrast. Om man har timdebitering.

/Pi
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
pfyra
Inlägg: 347
Blev medlem: 8 mars 2015, 14:14:44
Ort: utanför Karlstad

Re: Blandat Arduino-skoj

Inlägg av pfyra »

En rotary encoder för att ställa in tiden kan vara något att fundera över.
En rtc kan också vara ett lyft, den borde gå skapligt rätt utan justeringar (tänker mig typ en ds1307).
Användarvisningsbild
pi314
Inlägg: 5829
Blev medlem: 23 oktober 2021, 19:22:37
Ort: Stockholm

Re: Blandat Arduino-skoj

Inlägg av pi314 »

pfyra:

Jag visste inte vad rotary encoder kostade, men hittade 10 st. för 15€ här.
https://www.az-delivery.de/en/products/ ... 7695498336

Dom har även Arduino RTC (D1302) med batteribackup, 5 st. för 7 €.
https://www.az-delivery.de/en/products/ ... 8929474656

Jag får läsa på lite om hur man använder dessa.

Det står inte vilken typ av batteri som används, men det kan vara ett CR2032.

Vad är skillnaden mellan D1302 och D1307?

/Pi
Användarvisningsbild
rvl
Inlägg: 5814
Blev medlem: 5 april 2016, 14:58:53
Ort: Helsingfors

Re: Blandat Arduino-skoj

Inlägg av rvl »

Serieinterfacet skiljer, DS1307 har I2C.
För litet mer peng får man DS3231 som håller rätt tid väldigt bra.
Användarvisningsbild
carpelux
Inlägg: 1879
Blev medlem: 13 oktober 2007, 12:33:33
Ort: Varnhem

Re: Blandat Arduino-skoj

Inlägg av carpelux »

Jag kan rekommendera en DS3231.

Jag håller på med ett litet projet och hade behov av ett externt eeprom så jag tog en modul jag hade liggande med en DS3231 samt ett AT24C32 eeprom på. Satte tiden den 27/7 och kan inte se att den dragit sig öht mot datorns klocka när jag jämför manuellt. Den har gått ca 80 på ström och 20 på det inbyggda batteriet.
Skriv svar