Svenska ElektronikForumet
https://elektronikforumet.com/forum/

Skillnader i timers, prescalers på Atmega och STM32
https://elektronikforumet.com/forum/viewtopic.php?f=7&t=95924

Författare:  Janson1 [ 21.31 2019-08-14 ]
Inläggsrubrik:  Skillnader i timers, prescalers på Atmega och STM32

Hej alla, jag vet inte hur jag skall börja men... En Atmega 328 lär ha tre timers, 2st 8 bitars och en 16 bitars, samtliga med frekvensdelare och jämförelseingångar?
Nästa krets, en STM32F103C har 7 timers varav 3 st 16 bitars med div finesser och allt.
Jag har via Arduino "programmerat" en motorstyrning till dieselmotor (se ECU-styrning till VW pumpdysediesel) med Atmega328 kretsen och den fungerar numera bra, jag har därefter lagt till en pwm utgång och interrupt, allt fungerar ganska bra, mest lite injustering av div konstanter som inte är riktigt klart. Jag hittade sen en STM32F103Cxx modul som stöds av Arduino. Så jag lyckades lägga in mitt ECU-program med pwm utgång och det funkade men sen provade jag även med mitt interruptbaserade ECU-program och det fungerar med MEN det finns en störning typ interferens som ändrar sig med varvtal och belastning (spridarnas öppningstider). En person har hjälpt mig på distans att göra om coden och lägga in den på en STM32 Nucleo F103LRB men återkom att den är för liten, antalet timrar räcker inte utan han valde istället STM32 Nucleo F446 som har upp till 17 timers med extra allt? Min egentliga undran och fråga är: Kan man bara använda en timer en gång per programloop? Eller kan man initiera samma timer flera gånger i en loop och på så sett ha den till lite olika grejer? Är det skillnad i användningen av timrar i Atmega jämfört med STM32? Jag önskar om möjligt ett förståligt svar och jag hoppas jag skrivit en förståelig fråga...
Skall väl ochså tillägga att jag tittar i kretsarnas respektive datablad men jag blir inte speciellt klokare för det... Så tyvärr hjälper dom mig bara lite, ytterst lite.
edit: glömt en bokstav...

Författare:  Shimonu [ 22.23 2019-08-14 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Har bara erfarenhet med Atmega men känner mig säker att det är liknande i andra kretsar. Men timers är inget problems att ställa om och starta med andra inställning när som helst, sen om det fungerar bra med vad man försöker göra kanske inte alltid är sant.

Författare:  mrfrenzy [ 22.37 2019-08-14 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Den stora fördelen med en timer är ju att ställa in den och sen glömma bort den. Timern jobbar på i bakgrunden utan att belasta din mainloop.

Om du ska sitta och bevaka när en timer blir ledig för att återanvända den så är det risk att låsa in sig i ett ineffektivt hörn.

Det finns en anledning till att Bosch, Siemens etc sätter rejäla 32-bit mikroprocessorer med hundratals I/O i sina ECUer.

Författare:  hawkan [ 04.10 2019-08-15 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Inga problem att använda en timer till olika saker. Sker sakerna seriellt efter varann så är det enkelt.
Sker saker omlott så är det första man får fråga sej i ISRen: vad ska göras nu? Så,man får hålla ordning på det och man får göra sej en scheduler tror jag det kallas. Och ladda om timern. Men folk har funderat på detta förr. Det är inte första gången som antalet timers är lägre än antalet tasks.

Författare:  Icecap [ 06.53 2019-08-15 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Behöver man flera timers för att de ska sköta olika jobb är det en fråga om hur exakta i tid som de jobb måste skötas.

Har man t.ex. en funktion som ska utlösas var 133ms och en annan som ska utlösas var 150ms kan man - som exempel - ta en timer som ställs till att ge interrupt varje 1 ms.

I timer-ISR'n tar man sedan en variabel för varje funktion och gör såhär:
Kod: [Expandera/Minimera] [Hämta] (Untitled.txt)
if(Timer_Counter_x)
  {
  Timer_Counter_x--;
  }
else
  {
  Timer_Counter_x = 133; // Antal ms
  Do_The_133_ms_stuff();
  }

Ganska enkelt - men ger lite timingsjitter som man ska ha koll på om det är av betydelse.

Men blir det så att timingsjitter är ett problem ska man analysera noga vad som behövs och hur man uppfyller det. Att ha fler timers som är dedikerat är ingen hjälp, två timers med olika intervall och samma interrupt-prioritet kommer att ge timingsjitter per definition.

Författare:  ToPNoTCH [ 10.45 2019-08-15 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Här är nog ett typexempel på när man lider av att köra Arduino.

STM32 har väl utvecklade timers och en NVIC som har massa möjligheter.
Man kommer inte åt dessa via STM32duino utan kan enbart använda ordinarie funktioner.

Det är väl så att vissa timers och interrupter används default i Arduino (För millis(), PWM osv.)
Det är ju hyggligt dokumenterat för AVR vad som "är upptaget" men jag hittar inte mycket kring STM32duino.

Om koden funkar med AVR men inte STM32 (trots att den kompilerar) så är min slutsats att porteringen inte är fullt utvecklad.

Själv hade jag nog växlat till C i detta fall. För att få järnkoll på interrupter och timers.

Författare:  hawkan [ 11.52 2019-08-15 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Du menar att gå över till STs utvecklingsmiljö antar jag. Arduino är redan C.

Författare:  Shimonu [ 14.40 2019-08-15 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Det brukar väl påstås det men har för mig någon visade att det inte var det. Bara det faktum att man tvingas till setup och loop i Arduino gör väl att det inte är C. Och det är väl något mellansteg från en arduino-sketch tills det faktiskt körs genom gcc.

Författare:  AndLi [ 14.44 2019-08-15 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

hawkan skrev:
Du menar att gå över till STs utvecklingsmiljö antar jag. Arduino är redan C.

Vilken C standard anser du att är?

Det är möjligen en dialekt som måste preprocessas innan du kan ge den till en c kompilator som följer standard..

Författare:  ToPNoTCH [ 18.05 2019-08-15 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Vi kanske borde reda ut det en gång för alla då.

- Kontrollstruktur och Operators i Arduino är C++

- Variabel hantering är 99% lika som C

- Funktioner är till 95% properteriära.
Typ: digitalWrite() , pulseIn() , attachInterrupt() , Serial.print() osv.

Eftersom i stort sett (normalt) alla program använder någon peripheral och åtkomst till dessa i Arduino är via funktioner så är
i praktiken ingen Arduino kod kompilerbar i C, vare sig för AVR som Arduino ursprungligen utvecklades för eller för annat.

Det är väl just att man abstraherat bort konfigurering av hårdvaran som gör att det är ganska lätt att komma igång och koda i det. Samtidigt hämmar det ju lite utvecklingen nu när det kommer mer och mer stöd för andra MCU'r beroende på hur bra man porterar dessa funktioner till ny hårdvara.

När någon community adderar plattformsstöd för Arduino så har dom ju olika filosofi.
Vissa vill inte lägga till nya funktioner som bara funkar för den MCU'n och andra har inte ens alla "bas funktioner" som finns i Arduino referens på plats.

Med detta sagt så vill jag på intet sätt "se ner på" Arduino. Det är säkerligen hundratusentals programmerare som skulle gjort annat om det inte funnits. Det går att göra lika bra program i Arduino som i C och Assembler osv. Men det finns begränsningar i utnyttjandet av hårdvaran.

Jag själv använder det ofta och gärna ihop med Esspressif moduler.
Till STM32 så blir det dock C och gärna i Atollic nu när den blivit gratis dessutom.

Författare:  Janson1 [ 20.29 2019-08-15 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Mycket grejer här som jag inte förstår... Men varför har en STM32 variant 17 timrar? Är dess timrar låsta till specifika I/O:s? Om man använder en timer, kan dess I/O då bli oanvändbar om man använder den internt? Många och kanske konstiga frågor...

Författare:  AndLi [ 21.54 2019-08-15 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Nä io kan du då använda till andra saker som är kopplad till den eller som en vanlig IO.

Ja en timer har vissa specefika pinnar den kan ha som in/ut gång.

Ofta är det 3-4 olika varianter av timerar som kan lite olika saker.

Författare:  Icecap [ 06.49 2019-08-16 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Min erfarenhet av Renesas RX-serien är att det finns olika typer av timers.

På RX210 finns det t.ex. 4 st som enbart kan ställas till att ge interrupt som alltså kan användas till att utlösa sekvenser i mjukvaran. Dessa kan vara att utföra en regleringsfunktion med stabila mellanrum eller liknande.

Jag använder den typ av timer till att ha den basala time-tick där jag t.ex. läser knappar, utför debounce och liknande.

Det finns sedan två grupper om 6-7 st timers med lite olika egenskaper men i grunden mycket lika, de är till att interface med hårdvaran. Det kan vara 3-fas PWM för BLDC-styring, det kan vara Capture-funktioner (som jag använder en del) osv. De kan oftast "länkas ihop" så att t.ex. 3-fas PWM kan hållas synkroniserat vid att man kan ha en timer till att utlösa en annan timer osv.

Detta sätt går igen i "alla" µC med hårdvara nog.

Såklart har varje timer mest tillgång till vissa portpinnar - och det finns µC där man kan omkonfigurera vilka enheter som sitter till vilken portpinne - och därför ska man planera sitt design noga med datablad i handen.

Författare:  ToPNoTCH [ 22.46 2019-08-16 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

När det gäller planering så får man faktiskt säga att CubeMX är riktigt bra.
Många med mig gillar inte den "automagenererade setupkoden".
Men man kan skita i den och bara använda CubeMX som dokumentationsverktyg.

Efter man valt MCU så assignar man pinnar och grejor som man vill och verktyget har koll på vald MCU
så man kan inte göra fel.

Den har även en otroligt pedagogisk grafisk klock configurator.

Bilaga:
Namnlös.png

Författare:  Janson1 [ 08.16 2019-08-17 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Alltså, då jag egentligen inte riktigt fattar STM32 (ja kanske inte Atmegan heller) så blir det nog till att skaffa det här CubeMX-programmet och börja (försöka) programmera själv. Jag har 2 st Nucleo-moduler att ha igäl...

Författare:  Nerre [ 08.42 2019-08-17 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Jag tycker det här låter lite som när folk använder timer till fel saker.

Precis som mrfrenzy skriver så är en timer nåt man använder om man så att säga vill att nåt ska "ticka på med en egen frekvens". En timer ställs in och går sen fristående. Antingen har man den för att få en pinne att ticka på egen frekvens, med egen pulsbredd eller liknande, eller så använder man den för att köra en interrupt-rutin med viss frekvens.

Om man istället gör misstaget att tro att en timer är nån slags stoppur som man kan använda att vänta på för att få sin huvudloop att göra saker i rätt tempo så gör man oftast fel. Vänta på en timer ska man väl i princip aldrig göra, däremot kan man i sin loop kolla en timer och agera utifrån dess värde. Men då får man ju tänka på att man kollar "har timern passerat xxx", sen om det är xxx+1 eller xxx+100 kan man aldrig vara säker på (så det är ju en funktion man ska använda om man inte vill göra saker för tätt, men det funkar inget bra om man vill göra saker vid en exakt tid).

Författare:  ToPNoTCH [ 09.34 2019-08-17 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Jag är nog inne lite på din linje Nerre.

Samtidigt så är jag lite osäker på om TS egentligen har något problem.
1. Byte från Atmega 328 till STM32F103C med samma kod ger "interferens"
2. Killen som hjälper att göra om koden säger att det är för få timers i STM32F103C och växlar till F446

3. Och frågan är från TS är om man inte kan "Kan man bara använda en timer en gång per programloop"

Om vi delar upp det hela lite så blir nog svaren:
1.)
Om du kör samma kod mot annan MCU och får annat resultat så är Arduino porteringen till STM inte riktigt bra.
Det kan finnas workarounds och troligen bör du ställa frågan i något STM32Duino forum.

2.)
Det låter märkligt. STM32F103C Har 4 timers (3st 16 bit + 1st 24 bit) dvs. lika många som Atmega 328.
Beakta att 24-bit timern är SysTick och därför kanske inte kan användas hur som helst i Arduino (enl. tidigare inlägg).
Detta kan vara skälet att killen som hjälper dig får för lite timers.

3.)
Som IceCap beskrivit finns timers med olika syfte, men om avgränsar oss till en "normal räknare" så visst kan du använda den till fler saker. Det blir dock lite abstrakt när du skriver "per programloop" då man normalt inte använder dom i loopar på det sättet. Det är dock större risk att man går bort sig om man använder 1 timer till flera saker, i synnerhet med interrupt.
Vanliga misstag är:
- Man har för mycket kod i Servicerutinen (en högrprioriterad ISR kommer köra färdigt innan den hoppar vidare till en med lägre prioritet)
- Man förstår inte hur (eller har inte tillgång till via programspråket) man sätter upp ISR prioriteteter länk
- Man reinitierar timern eller interruptflaggan efter man genomfört ISR (innebär att man förskjuter tiden med lika mycket som det tar att köra ISR koden)
- osv. osv.

För att ge ett tanke experiment:
Tänk att du vill ha 3 olika saker utförda.
Sak 1 varje sekund
Sak 2 varannan sekund
Sak 3 var tredje sekund

Vad blir skillnaden med en timer respektive tre olika ?
Var tredje sekund skall alla saker köras samtidigt vilken körs först (i båda fallen med 1 och 3 timers) ?

Författare:  Nerre [ 10.02 2019-08-17 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Precis, i ett sånt exempel använder man väl bäst en timer på 1 sekund, sen får interrupt-rutinen hålla reda på 2 och 3 sekunder mha en räknare (variabel).

Författare:  Janson1 [ 23.19 2019-08-17 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Jag tror faktiskt jag förstod lite av det sista nu, framför allt så tror jag ni har förstått mitt dilemma... Men, jag har själv börjat med lite felsökning, vad fungerar/fungerar inte. Och för det första så har jag skrivit fel i koden, man måste dels göra om: istället för analogWrite så skall det vara pwmWrite. Sen så har STM32 inte 255 steg utan 65535 steg. Sedan är analogingångarna 12 bitar istället för 10 som Atmegan har. (detta visste jag i och för sig sen förut) Även i pinMode skall man välja PWM resp INPUT_ANALOG, PWM hade jag missat... Sen så skall man nog undvika PULLUP om man kör in 5 volt på ingången även om den är "5 volt tolerant" för det blir ju inte bra för resten av kretsen så det har jag sedan tidigare tagit bort. Nu är klockan läggdags men i morgon skall jag prova dessa förändringar/förbättringar...

Författare:  Janson1 [ 06.49 2019-08-18 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Nu är det testat och det fungerar INTE (än) Det jag avser är pwm-utgången. Så här har jag gjort: Använder en int som gasPin = PA0, den pinnen klarar analoginsignal 0-3,3 volt. pinMode(gasPin, ANALOG_INPUT); (räcker med INPUT, utan ANALOG, det verkar fungera ändå) Jag har sen gjort om gasvärdet 0-255 till 0-65535 via MAP och det fungerar, kollat via Serial.print-funktionen. Men på slutet så skiter det sig. Enligt: https://circuitdigest.com/microcontroll ... ed-Control så skall jag använda pwmWrite(berördutgång(med tildetecken), värde); istället för analogWrite som förut.
kompilatorn sväljer pwmWrite men det är inte rött som tex analogWrite blir. Så jag tror nåt är vajsing runt detta...

Författare:  Janson1 [ 06.56 2019-08-18 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Testade att lägga in den filen enligt länken ovan och där fungerar pwm funktionen men inte ihop med min ECU, så det är nog en konflikt någonstans?

Författare:  ToPNoTCH [ 09.24 2019-08-18 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Använder du samma pinne i ditt program som dom gör i testprogrammet som funkar ?

Författare:  Janson1 [ 12.55 2019-08-18 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Japp, jag gjorde tom om testprogrammet till "mina" pinnar från början så jag vet till 100% att det funkar att göra så här.

Författare:  ToPNoTCH [ 14.35 2019-08-18 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Då måste väl nästan den enda förklaringen vara att just den timern som används för PWM på just vald pinne redan är upptagen med något annat.

Jag försökte hitta lite hur dom assignar timers till pwmWrite och det enda jag hittat så långt är att det blir olika timers beroende på vilken pinne.

Jag tycker det är ruskigt dåligt dokumenterat.
Mycket av platfformstödet verkar ha ärvts av MapleLabs som var pionjärer med att få Arduino att köra på STM chip. Deras kort (MapleLeaf) tror jag dock inte säljs längre.
Det finns dock lite historisk dokumentation kvar LÄNK

Om du inte klantat dig (du verkar noggrann) på något sätt i koden så skulle jag rekommendera att du kikar lite på övriga funktioner som du använder och som kanske lägger beslag på samma timer på något vis.

Jag tror den här pin map'en även visar vilken timer som används till PWM för respektive pinne
Bild

Författare:  Janson1 [ 15.11 2019-08-18 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

TopNotCH: det var en bättre bild på "Blue Pill" modulen än vad jag sett hittills. Det skulle nog mycket riktigt vara vilken timer som är hårdvarukopplad till vilket ben. Det jag ser direkt nu är att jag valt PB0, PB1 som ingångar för vev resp. kamgivare och dom skall inte vara 5 voltstolleranta och det är dom ända benen som fungerar direkt... Jag vet inte hur känsligt det är men nu har ECU:n gått med lysdioder nåt dygn med 5 volt rakt in från motorsimulatorn som är en Atmega328 med 5 volts drivning. Hmm, kanske skulle sätta nåt slags motstånd i serie eller dubbla motstånd så det blir 3,3 volt?
PB0 använder då timer 3 och PB1 använder timer 4 och min elfläktsutgång som jag satt på PA6 använder timer 1.
Skall man läsa det så? Vad betyder PWM2/2 resp PWM2/3? Vad är vad?
Innan fler frågor så skall jag läsa din länk också, det kanske blir självklart sedan...

Författare:  Janson1 [ 06.07 2019-08-19 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Den här leafLabs sidan om maple-modulen är ganska bra, jag har kollat igenom en del där men kan inte hitta specifikt vilken timer som går till vad. Timer 4 verkar vara till PWM för alla utgångar. Vad jag förstår så om man har alla PWM igång samtidigt så startar dom alla samtidigt men beroende på var man sätter stopptiden (duty) så stängs PWM utgångarna av en efter en tills timern går i botten (overflow) och då börjar alla utgångar om på nytt. Maxvärdet är 16535. Så långt fattar jag nog... I mitt fall så verkar mitt ECU-program ha lagt beslag på denna timer 4 till nåt annat? Om så är fallet, hur luskar man ut det? Jag använder ju PB1 som ingång och det står ju PWM3/4 på det benet också. Enklast vore kanske bara att helt random välja en annan pinne för denna ingång?

Författare:  ToPNoTCH [ 09.33 2019-08-19 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Jo...Så skulle jag nog gjort.

Annars ta en backup på koden.
Ta bort alla definitioner som använder Timers då skall det ju hoppa igång.
Sedan lägga tillbaka dom en efter en och se vilken som sabbar.

Alternativt tar du exempelkoden som du fick att funka och lägger på dina definitioner på den, en efter en.
Tanken är att ringa in vilken funktion som konfliktar med din pwm.

Författare:  Janson1 [ 10.09 2019-08-19 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Jag börjar nog med att "vetenskapligt" random med att välja andra pinnar som utgångar/ingångar för att se om det hjälper...

Författare:  Janson1 [ 20.25 2019-08-19 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Ingenting av det jag nu provat hjälper. Jag tror inte jag kommer längre och dessutom saknar jag programmeringskunskap. Jag har läst en del men blir väl egentligen inte så mycket klokare. Finns det något lättläst som förklarar timer och frekvensdelare på ett väldigt enkelt sätt? Jag har ju skrivit koden i Arduinospråk och detta fungerar felfritt i NANO:n. I och med att jag använder Arduinospråk så ser jag inte när och vilka timrar jag använder men förmodligen behövs timer för millis, micros, delay, interrupt, PWM. Skall väl tillägga att denna tråd är en utbrytare ur "ECU-styrning till en VW pumpdysediesel" så fixar sig inte detta problem med Blue-Pill modulen så får jag helt enkelt släppa tanken på att uppgradera från Atmega till STM32...

Författare:  baron3d [ 21.36 2019-08-19 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

https://www.st.com/content/ccc/resource/technical/document/application_note/group0/91/01/84/3f/7c/67/41/3f/DM00236305/files/DM00236305.pdf/jcr:content/translations/en.DM00236305.pdf

https://www.youtube.com/watch?v=DyyYaGU4biY

https://www.youtube.com/watch?v=DQFvV3DJL54

Författare:  Janson1 [ 16.43 2019-08-20 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Nu har jag tittat igenom länkarna och det är mycket matnyttigt men jag kan inte se vilken timer som går till vad. (alla 4 verkar generella?) Jag går helt enkelt bet...

Författare:  Janson1 [ 20.27 2019-08-22 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Jag fortsatte med Atmegakretsen i NANO-modulen och la in tre st pwm utgångar samtidigt som ECU:n gick och allt verkar fungera ihop. Det blir nog att fortsätta med Arduino och dess IDE-miljö då allting verkar funka...

Författare:  MattisLind [ 09.39 2019-08-29 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Ursäkta intrånget i tråden, men jag blir så fundersam över de ständiga diskussionerna om Arduino och att det inte skulle var C/C++ så jag kunde inte hålla mig denna gång.

AndLi skrev:
hawkan skrev:
Du menar att gå över till STs utvecklingsmiljö antar jag. Arduino är redan C.

Vilken C standard anser du att är?

Det är möjligen en dialekt som måste preprocessas innan du kan ge den till en c kompilator som följer standard..


Att man i ett byggsteg gör en massa saker innan man kör det genom kompilatorn har väl ingenting med vilket språk det rör sig om. Inte dialekt heller. Arduino använder en vanlig GCC. Inga konstigheter.

Här är en länk som beskriver byggprocessen: https://github.com/arduino/Arduino/wiki/Build-Process

Det är inget märkligt med Arduino-miljön. Man kan lägga in sina cpp och h filer som man önskar och den bygger ihop det. Man måste dock ha en ino fil som bas för projektet. Och den har ingen main() eftersom den ligger in i en fil i ramverket. Men det har som sagt inget med språket som sådant att göra. Sedan är det så att en del library-funktioner är lite speciella och har sina ideer om hur saker ska göras vilket kan ge begränsningar. Men det har ju inget med språket att göra.

Att inte kalla det för C++ bara för man inte har en main() i .ino filen håller jag inte med om. Man kan kalla Arduino för ett C++ ramverk.

Författare:  Mr Andersson [ 11.46 2019-09-01 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Nu är det ju inte enbart att det inte finns någon main(). Översättaren gör även en hel del annat.
T.ex. behöver du inte fördefiniera funktioner. Det är, enligt mig iaf, en förbättring men det bryter mot standarden.

Att säga att det är c++ bara för att gcc används i bakgrunden är inget vidare argument. Den läser ju aldrig de omodifierade filerna.
Om jag skriver kod i pascal och kör det genom en automatisk översättare och kompilerar med gcc, har jag då skrivit c++-kod?

Ordet arduino kan innebära flera olika saker.
Arduinohårdvaran. Kan programmeras med valfritt språk som stödjer processorarkitekturen.
Arduinoramverket. Kan användas av valfri kompilator som kan läsa gcc-bibliotek. (eller någon av alla de tredjepartsportar som finns)
Arduinospråket. Väldigt likt, men är inte, c++. Arduino själva kallar det Arduino Programming Language.
Arduinoplattformen. De tre ovanstående tillsammans.

Det är absolut inget fel att använda arduino-IDE:t. Men det är fel att säga att det är c++. Säg istället att det är likt eller baserat på c++.
Kanske ses som petitesser av somliga, men att följa standarder är viktigt. Annars slutar det med att alla gör sina egna c++-språk och inget fungerar tillsammans.

Författare:  Janson1 [ 11.51 2019-09-01 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

En undran: Har jag någon glädje av Arduino´s C prog eller ej? Kan detta hjälpa mig att komma på dom olika timrars funktion/ickefunktion?

Författare:  Icecap [ 14.17 2019-09-01 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Problemet är inte språket! Problemet är att Arduino-användare sällan har bra koll på vad som sker med hårdvaran inuti µC'n och därför sällan använder den "korrekt" och fullt.

Såklart finns det användare som är helt med på exakt hur hårdvaran fungerar och vad som sker "bakom draperiet" - men de är mycket få och jag har aldrig hört om någon - ändå är jag säker på att de finns.

T.ex. medför funktionen systime() (tror jag den heter) att en timer kör med fast 1ms interrupt och uppdaterar en 32-bitars variabel. Detta är en god sak till mycket - men använder en timer man kanske skulle ha till annat om man har ett projekt av en viss dignitet.

Såklart finns det work-around på detta - vilket betyder att miljöns (Arduino) påverkan är negativ på lösningen då man måste ta över funktioner som är inbyggd i miljön. Inte optimalt.

Jag är ganska säker på att det går att hooka en interrupt up och använda det till olika hårdvarafunktioner - men hur många användare gör det i verkligheten?

Nu är "original"-Arduino i grunden inget annat än en lite trött µC med en bootloader i samt en USB-port för ICSP. Den funktion har jag på en Renesas RX210 32-bitars µC också, dock utan att USB-delen sitter fast på kretskortet.

Så det är inget speciellt i det, jag har använd EXAKT samma interface till ICSP till Fujitsu FFMC-16LX och Renesas RX210 och det enda jag behöver på min programmeringsdator är en seriell port, vara sig en inbyggd eller en USB-dongel samt ett litet interface med en MAX232 på.

Det "enda" Arduino-miljön ger är att portpinnar inte kallas vid deras namn (PORTA.B0 eller liknande) men istället översätter dessa till vilken pinnummer det är på kretskortet.

Det finns färdiga funktioner för att säga att en viss pinne är In/Ut/Analog/Digital osv, något man klarar på ett piss-kvart med ett datablad i handen.
Det finns färdiga funktioner för att aktivera A/D-omvandlaren, igen en sak man klarar mycket enkelt själv.

I det hela tagit erbjuds en hel del funktioner som gör att man kan lösa många uppgifter utan att behöva gräva i hårdvaran och utan att förstå hårdvaran.

Men som all annan förtuggad mat blir resultatet blekt och smakslöst. Jag tänker alltid på dessa barnmatsburkar/glas man kan köpa när jag hör om Arduino: blek mat som inte smakar något alls - men barnen kan leva på det, det är bara inget kul.

Sedan kommer fördelen vid Arduino: "alla" kan programmera! Just för att alla funktioner är förtuggade och att det läggs till vissa funktioner per default fungerar miljön enkelt och smidigt - och man behöver inte fatta vad man egentligen jobbar med.

Detta gör instegsnivån lågt och det är bra. Jag använde runt 1,5 år på att laga de rutiner jag behövde till RX210, då har jag å andra sidan ett rikhaltigt bibliotek med samtidig interrupstyrd kommunikation på 5 UART, Capture på 8 kanaler, radiokommunikation, A/D-omvandling som håller koll på om in-spänningen är inom giltiga parameter så att 12V->5V omvandlaren kan köras (vid drift av LED-display), ljussensor-omvandling osv. Timerstyrd 1-Wire® kommunikation med det hela och vad annat jag behövde.

Samtidig är det också vad som är problemet om man vill gå vidare: Arduino har rimligt effektivt klippt banden mellan hårdvaran som den finns i µC'n och programmeringen.

Visst, att tugga sig igenom 1600+ sidor datablad för att lära sig hur tusan man sätter en portpinne rätt är definitivt avskräckande för vilken nybörjare som helst! Kommer man upp i "storlek" på µC behöver man dock göra detta jobb och jag skulle gärna se Arduino erbjuda det utbildningsmaterial som förklarar hur det sker, vilka funktioner som läggs till osv.

Författare:  Janson1 [ 19.23 2019-09-01 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Jo det är väl lite detta som är problemet, antingen får jag köra vidare med "färdigtuggat" eller får jag sätta mig ner och läsa på utan h*lv*te tills det klarnar... Skall nu ge mig på Nucleo så smått. Får se vad det ger...

Författare:  hawkan [ 07.18 2019-09-02 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Icecap skrev:
Samtidig är det också vad som är problemet om man vill gå vidare: Arduino har rimligt effektivt klippt banden mellan hårdvaran som den finns i µC'n och programmeringen.


Detta är inte sant. Arduino erbjuder sin standardmiljö med en del färdiga funktioner, och sin utvecklingsmiljö.
Men i botten är det avr-gcc och ALLT den kan, går att göra i arduino-miljön. Det finns inget hinder att
leka med bittar och register, t ex initiera om en eller alla timers, eller ja precis vad som helst man vill göra.
Här finns inget man har klippt bort, allt från avr-gcc finns tillgängligt. Arduino är inte problemet.

Författare:  Swech [ 10.59 2019-09-02 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Har man bestämt sig för en åsikt så har man...... :roll:
Hatet mot arduino är lite flyktigt och ändrar sig beroende på de svar som kommer in
nåja, en annan hatade ju Amiga då det begav sig..

Swech

Författare:  Janson1 [ 07.56 2019-09-11 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Jag funderar vidare, mina problem med 32 bitars processorn och dess timers behöver inte var timerfel bara...
Jag såg på en youtubevideo att man måste deklarera om int till int16_t om man måste ha en specifik längd.
Jag har ju byggt min ECU med int, byte, float med hänsyn till vad jag behöver som mest hela tiden i datavärde.
Jag tror detta kan ställa till problem lite här och var så det blir till att exakt ange vad som skall gälla, och sen testa...

Författare:  hummel [ 08.15 2019-09-11 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Har du gjort någon design på ditt program i form av flödesschema eller liknande (valfri desigmetod går bra)? Det är alltid en bra start att designa innan man börjar programmera. Sedan testa varje möjlig modul av mjukvaran och verifiera funktionen.

Författare:  Icecap [ 09.29 2019-09-11 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Janson1: Om en variabel bör vara av en specifik storlek är det praxis att man just definiera dom till t.ex. uint16_t eller vad man behöver.
Samtidig ska man ha klart för sig att bara för att en variabel bara behöver vara en byte är det inte säkert att man ska ange den som 1 byte...

Exempel: en 32-bitars µC, man behöver en flagga som är antingen SANT eller FALSK. Detta motsvarar rent faktisk 1 bit.
MEN - det rör sig om en funktion som kallas oerhört många gångar och därför ska den vara snabb som tusan.

I "många" 32-bittare kan man bara läsa en 32-bitars variabel in, ska man använda en byte i dom ska det shiftas & maskas bittar - vilket kostar tid. Och då ger det mening att använda en 32-bitars variabel (int eller unsigned int) trots att det räcker med 1 bit.

Är det däremot en variabel som ska kollas "sällan" har lite extra overhead ingen stor betydelse och man kan fint använda bytes eller även bits om man vill.

Men det är mycket viktigt att planera hur man vill lösa problemet som programmet skal lösa som hummel skriver.
Jag använder mycket ofta att skriva rutiner i form av deklarationerna och sedan en text som anger vad rutinen ska lösa.
I toppen av en källkod skriver jag alltid hur det hela är tänkt att jobba och ganska ofta kladdar jag på papper när jag ska börja stycka ihop funktionernas flöde.

Författare:  Janson1 [ 10.35 2019-09-11 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Från början så hade jag bara Arduinos IDE inställt på UNO/NANO/MEGA, alla 8 bitare och en int där är 16 bitar så när jag "designade" (Är väl att ta i) tänkte ut dess funktioner så utgick jag ifrån hur lång en int är, om jag behöver signed eller unsigned osv. I dessa fall behövdes ju inte vidare eftertanke med att låsa dom till en specifik längd. Men nu behövs det förmodligen.
Sen det här med design och flödesschema, det är jag otroligt dålig på, jag har försökt men det är knappt jag kan tyda det själv efter ett tag. Däremot så skriver jag mycket kommentarer efter i princip varje programmeringsrad, det är mitt sätt att komma ihåg. Jag sitter nu och felsöker på en 32bitars SAMD processor från Atmel och jag tror man måste deklarera en Array på ett annat sätt än vad Arduinos IDE föreskriver? Jag har konstaterat att den delar ut rätt nummer i arrayen men det är bara första som fungerar. Jag behöver nog klistra in filen också?

Författare:  Icecap [ 11.22 2019-09-11 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Altså - int är en farlig storlek att använda! Den kan vara allt från en byte till 4 byte! Och till och med mer.
Är det ett värde som kan vara i en byte kan man använda int utan problem men ställer man krav på t.ex. minsta storleken måste man använda andra sätt.

Författare:  Janson1 [ 15.12 2019-09-11 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Jo men jag får helt enkelt börja skriva exakt vad jag behöver i fortsättningen. Arduinos IDE stödjer detta dessutom.
Nu verkar det inte vara detta fel denna gång, men jag felsöker vidare...

Författare:  sodjan [ 15.32 2019-09-11 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Klassisk felsökning. Skala ner. Fixa ett minsta möjliga "reproducer".
Om en speciell funktion strular, gör ett program med enbart det.
O.s.v. o.s.v...

Författare:  Janson1 [ 07.35 2019-09-12 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Tyvärr verkar "klassisk" felsökning inte funka här. Jag har kommit på att var för sig så funkar det så det är nog ingen skillnad på sättet att skriva arrayer. Allt jag har skalat ner funkar var för sig men inte ihop och då faller konceptet lite... Eller rättare sagt: Det funkar i Atmega328-kretsen men inte i STM32 typ "Blue pill" eller Adafruit "Itsy Bitsy". Detta är lite varför jag skapade denna tråd, jag misstänker att det just är en timerkollision. Bara frågan hur man skall komma förbi felet, är det ens möjligt? Jag tror STM32:s arkitektur inte passar att bara lägga in samma upplägg som på Arduino. En Atmega328 verkar bara ha 3 timrar (2 8 bitar, 1 16 bitar) medans STM32 har från 4 upp till en hela tjog med timrar men det verkar vara svårare att återanvända en timer flera gånger i loopen på STM32 medans på Atmega328 går det alldeles utmärkt? Detta är vad jag kommer fram till som lekman...Jag hoppas jag har fel där. Mer som jag kommit fram till är att det kanske är bästa alternativet för mig att faktiskt behålla den lilla NANO:n med 328 kretsen på. I går så hittade jag en uppdaterad version av NANO:n, den heter NANO Every och har en 8 bitars processor som heter Atmega4809. Jag beställde två stycken som prov... Den går på 5 volt, den har samma fotprint. edit: felstavning

Författare:  adent [ 07.48 2019-09-12 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Swech skrev:
Har man bestämt sig för en åsikt så har man...... :roll:
Hatet mot arduino är lite flyktigt och ändrar sig beroende på de svar som kommer in
nåja, en annan hatade ju Amiga då det begav sig..

Swech


Och jag som tyckte du var vettig :verysad: ;) Men det kanske lagade sig?

Författare:  Swech [ 09.36 2019-09-12 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Atari var myyyyket bättre... om man inte jämförde alla delar så noga.... :D

Swech

Författare:  Icecap [ 11.33 2019-09-12 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Janson1: "...det verkar vara svårare att återanvända en timer flera gånger i loopen på STM32..."

Om det finns en "hög" med timers - varför då återanvända?

Hur många behöver du? Om det är 20 olika sekvenser som ska köras igenom är det en sak, om det är 4-5 saker som ska hända regelbundet är det en annan sak.

Författare:  Janson1 [ 13.02 2019-09-12 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Ja, det är det som är grejen, finns det en driva timers så behöver man inte återanvända. Men Blue Pill, Adafruit, feather m0 mm. är byggda på/runt ganska "små" STM32 kretsar som just bara har 3-4 timers. Hur många timers behöver jag? Svar: vet ej, än...
Jag sitter lite fast i Arduinostuket men jag har skaffat CubeMX och Atollic och ett par Nucleomoduler, en 103 och en 446 tror jag den heter. Men att få till nåt vettigt (för mig) av detta blir en ganska lång startsträcka. Visst, att få till en blinkande lysdiod var framkomligt men en hel ECU-styrning är det mer meck med... Och där tror jag att jag kommer att gå bet? Eftersom jag programmerat i högnivå så vet jag ju inte riktigt vad som händer i källaren. Att hitta dels dokumentation på begripligt sätt (gärna svenska) och dels hitta lättöverskådliga exempel på programmering är inte det lättaste. Jag har fått låna en bok på prov om STM32, 850 sidor engelska. Jag är nu på sid 90... Här är senaste alstret som fungerar bra på NANO:n
Kod: [Expandera/Minimera] [Hämta] (Untitled.txt)
    // Nu helt ny med Interrupt på vevpin (2) 2019-05-13 och inlagd 2019-08-xx med en del småjusteringar i const. (se Lenovos program, nu inlagt)                                                               
    // Tändlägesjustering verkar ua ochså.                                                              Fungerar
    // Nu läser den av alla analogread i följd om 2 och 2                                               Fungerar
    // Batterispänningens inverkan grovjusterad                                                         Fungerar
    // En individuell möjlig iför injustering per spridare finns med.                                   Fungerar
    // Ändrad i gasen så analogvärde 20 är tomgång och analogvärde 210 är fullfart                      Fungerar
    // Ändrad till att starta insprutningsmodulen på tand 16 (case 16)                                  Fungerar
    // Mjukstarten är förbättrad och går in vid ca 200 RPM och varar till ca 450 RPM                    Fungerar
    // Några fler constanter har kommit till bla. gaspotmin, gaspotmax, utanvärde,                      Fungerar
    // En dubbel förtändning har kommit till, en för start och en för drift.                            Fungerar
    // En ny regleringsmetod inlaggd                                                                    Fungerar
    // En ny delta2 har tillkommit för ökad mängd mellan 200 till 450 rpm                               Fungerar
    // En styrning för yttre kylfläkt fixad, styrs nu av gasens börvärde   NYTT                         Fungerar
    // En aktiv/passiv funktion för elfläkten inlaggd, följer ECU aktiv/passiv                          Fungerar
    // Fasttidsfunktionen är förbättrad, funkar nu på alla 4 grundtider    NYTT                         Fungerar
    // senasteinsprdrift = 8.5; Detta är ändrat från 8.0 pga lite knack vid belastning låga varv.       Fungerar
    // Ändrat: senaste insprutning från 2.0 till 3.0 (start)faktor 1100 till 2000 för att få tidigare/mer gasrespons låga varv. skall testas
    // Funnit ut att det är totaltid som begränsar, ändrat från 11 till 12...
    // Pga av interrupt så måste alla durationstider inom tandräkning dubbleras, eller??
//-------------------------------Här börjar programmet---------------------------------------------------------------------------------------------------------------------------------   
            // här är olika justerbara parametrar (Konstanter) som påverkar enligt följande:
    const byte totaltid = 7;            // totaltid för case 15: x * motorns duration * 2 (10)tand 15-22 = max 14 totalt
    const int minfart = 7600;           // lägsta startvarv för spridarfunktion (3800 = 131 RPM)
    const byte startmangd = 32;         // avgör max startmängd 16  ca 19 grader ontid (16) mellan 131 till 200 RPM (absolut första början)
    const int faktor = 1500;            // en hur mycket effektökning skall gälla vid gaspådrag.(1100)ändrad till 1400 till 2000
    const int lagmangd = 4;             // max lågvarvsmängd 2 = 1 vevaxelpuls = 6 grader ontid (under tomgångsvarv)(2) 200 till 450 RPM (mjukstartsmängd)max 5 pga 16383 uS!!!
    const int tid1 = 4800;              // tid 1 är för att hitta pulsluckan vid start/lågvarv < 300 RPM (2500)                           
    const int tid2 = 2500;              // tid 2 är för att hitta pulsluckan i mellanvarv 1100--> (1500)
    const int tid3 = 1600;              // tid 3 är för att hitta pulsluckan i alla andra förekommande varv 1100--> (900)
    const int tid4 = 180;               // tid 4 är för att hitta pulsluckan på högsta varvtal (90)
    const float senasteinsprdrift = 4.6;// Vid tomgång/drift ges en ny "senasteinsprutningstid" som behålls sedan. (högre tal ger senare tändning)
    const byte tidigasteinspr = 240;     // kortaste insprutningsfördröjning vid maxvarv, högre tal ger tidigare tändning(110)(max 255)
    const float korrfaktor = 1.3;       // korrektionsfaktor för att senare lägga insprutningsbörjan till högre varv
    const float minstaAggrFaktor = 1.8; // gasrespons, den minsta förekommande (2.5)
    const int sprtroghet = 400;         // ett grundvärde för spridarnas påslagsfördröjning i uS (400)                     
    const int sprdiff1 = 0;             // en ev tidigareläggning av spridare 1 om den avviker i startfördröjning (uS)
    const int sprdiff2 = 0;             // en ev tidigareläggning av spridare 2 om den avviker i startfördröjning (uS)
    const int sprdiff3 = 0;             // en ev tidigareläggning av spridare 3 om den avviker i startfördröjning (uS)
    const int sprdiff4 = 0;             // en ev tidigareläggning av spridare 4 om den avviker i startfördröjning (uS)                                 
    const int omslagstartdrift = 3000;  // Bestämmer när mjukstarten går ur (omslagspunkt) (900 = brytvarv 450 RPM) skall vara 1200!!
    const int omslagmillimicro= 4000;   // omslag från milli till micro i case 16 (vid startvarv ca 200 RPM, baseras på mduration i us)2500
    const byte utanvarde = 25;          // om delta under vist värde utanvärde, nollas
    const byte gaspotmin = 20;          // gaspotens minsta tillåtna värde
    const byte gaspotmax = 210;         // gaspotens största tillåtna värde
    const int lagstavarv = 1140;         // tomgångsvarvet 500 uS motsvarar ca 800 Rpm (545)(550)
    const byte hogstavarv = 210;         // fullgasvarvet 90 uS motsvarar ca 4000 RPM  (90) (112)

                // dom olika variablerna
    float senasteinspr = 2.5;         // senaste insprutningstid (vid start upp till tomgång)(6.0 = 3 vevaxelpulser = 18 grader delaytid(2.0) Tomgångsförtändning.
    int fasttid = 180;                // Fasttid = börjar alltid på 300 för att sedan ställa in mer rätt (tid1 till tid4)
    int battVolt = 400;               // mäter systemspänning till spridare grundsatt till 400 för att snabba på start
    int sprstartkorr = 400;           // spridarstartkorregering i uS, spänningsberoende grundsatt till 400 för att snabba på start
    byte tand = 0;                    // vevpin räknare 0 till 28, i alla fall till 26
    byte visare = 0 ;                 // pekare för att välja rätt spridarutgång, startar på 0
    byte grundfart = 50;              // Elfläktens lägsta fart
    int flaktfart = 255;              // max  elfläktsfart (max 255!!)
    float aggrfaktor;                 // ett uträknat decimalvärde
    unsigned long delvalue;           // delvärde av pulstid i uS.
    unsigned int ondelay;             // tillslagsfördröjning spridare i uS/mS (mS inne i case 16)
    long puls, priv;                  // pulstid, föregående pulstid
    unsigned int delta, delta2;       // delta (totalöppningstid) i uS(mS) och en delta2 vd start
    float error;                      // error = varvtalsfelet i decimalform
    float starttandf;                 // starttand i decimalform för att få startfördröjningstid och finkorrigering av öppninstiden +-.
    float  mduration, bduration;      // varvfelet = motorduration/börduration i decimalform
    byte gas;                         // gas 0-255
    int fart_flakt;                   // gas för elfläkten
    byte analogval;                   // En switch/case till analogread
    int sprtroghetklar;               // korrektion för den inbyggda påslagströgheten i spridarna
    int spridardiff;                  // en ev. individuell spridartid korrigering (uS)
    volatile unsigned long VEVTAND_langd; // nuvarande tandlängd
    volatile unsigned long VEVTAND_start; // tandstart
    unsigned long prev_langd;             // föregående tandlängd
    volatile int caseRead;                // om case x är läst eller ej
   
                 // Dom olika I/O anslutningarna
    int vevpin = 2;                   // pulsingång vevaxelgivare, (aktivt låg).
    int kampin = 3;                   // kamaxelgivarens ingång, (aktivt hög).
    int pulsutpin = 7;                // pulsutgång 2 pulser per varv (kontrollutgång för övervakningen).
    int sprpins [] ={11,10,9,8};      // till spridarna (blir aktivt höga)
    int Disable = 12;                 // aktivt hög stoppar utsignalerna till spridarna
    int sprControl = 13;              // kontrollutgång för spridare till övervakningen
    int elflakt = 6;                  // PWM-utgång till motorns elkylfläkt (måste ha ett tildetecken)
   
 void setup()                         // körs bara en gång vid uppstart/reset                   
 {               // här ges alla I/O dess funktion   
   pinMode(vevpin, INPUT_PULLUP);     // satt vevpin som ingång (2)
   attachInterrupt(digitalPinToInterrupt(vevpin), VEV_pulse, RISING);      // här blir inpin interruptstyrd                     
   pinMode(kampin, INPUT);            // satt kampin som ingång (3)
   pinMode(sprpins[visare], OUTPUT);  // spridarutgångar satta som arrey (11,10,9,8)
   pinMode(sprControl, OUTPUT);       // en spridarutgång som blir hög varje gång en spridare öppnas (13)(Övervakningen)
   pinMode(Disable, INPUT_PULLUP);    // ECU väljare Hög = on, Låg = off (12)
   pinMode(pulsutpin, OUTPUT);        // satt pulsutpin som utgång (2 pulser per varv)(7)(övervakningen)
   pinMode(elflakt, OUTPUT);          // satt som utgång
   
   //Serial.begin(250000);            // bra att ha...
 }

//----------------------------------------Här börjar själva programloopen, denna körs hela tiden------------------------------------------------------------------------------------------
    void loop()
 {     
                                    // Det får plats ca 1700 klockcykler mellan varje x tal(case) (1 till 17)
                                    // Det tar lite mer än 100 mikrosek att läsa av en analogingång,
                                    // så ingen analogRead här, skall vara i case 16!
                                   
                                 
     if (digitalRead(Disable)==LOW)     // Disable låg stänger av ECU:n och gör den passiv
      { 
      delta = 0;                        // Genom att delta (insprutningstid) förblir 0.
      pinMode(sprpins[visare], INPUT);  // Gör om spridarutgångarna till ingångar för att ej belasta
      pinMode(sprControl, INPUT);       // Gör om spridarcontrollen till ingång för att ej belasta
      pinMode(elflakt, INPUT);          // gör om elfläktsutgången till ingång för att ej belasta
      }
     
     else //*
      {
      pinMode(sprpins[visare], OUTPUT); // Vid aktiv så gäller spridarutgångarna som utgångar igen.
      pinMode(sprControl, OUTPUT);      // Vid aktiv så gäller spridarcontrollen som utgång igen
      pinMode(elflakt, OUTPUT);         // Vid aktiv så gäller elfläksutgången som utgång igen
      }                            //*Detta är normalläget, samma som i setup*
     

 
     if (digitalRead(kampin)== HIGH)   // varje gång kamaxelns hempuls detekteras så resetas 4 räknaren
      {
      visare = 0;                      // resetas till 0. dvs cylinder 4 blir aktiv
      }
     
      if(caseRead == 1)
  {
    caseRead = 0;
    switch (tand)            // här startar switch och case, tandräknaren stegar fram ett steg (case)
  {
     case 0:                                         // lägger in rätt spridare till rätt spridardiff 
     case 30:                       
          if (visare == 0)                           // om spridarpekaren pekar på 0 (ben D11)
           {
           spridardiff = sprdiff4;                   // skall det individuella värdet för spridare 4 hämtas
           }

          if (visare == 1)                           // om spridarpekaren pekar på 1 (ben D10)
           {
           spridardiff = sprdiff2;                   // skall det individuella värdet för spridare 2 hämtas
           }

          if (visare == 2)                           // om osv... upp till 3 (fjärde spridaren)
           {
           spridardiff = sprdiff1;                   // ben D9
           }

          if (visare == 3)
           {
           spridardiff = sprdiff3;                 // ben D8
           }
     break;
     
     case 1:               // Detta case ger första pulstid
     case 31:
          delvalue = VEVTAND_langd;            // Första pulstid läggs in som deltid 1
     break;
     
     
     case 2:              // Detta case ger andra pulstid + batterispänningskontroll
     case 32:
          delvalue = VEVTAND_langd + delvalue;                     // föregående pulstid + föregående deltid läggs ihop
          sprstartkorr =map(battVolt, 150, 700, 400, 0);  // batterispänningen blir spridartidskorrigering
          sprstartkorr = constrain(sprstartkorr,400,200); // för att hålla färdigvärdet inom 400-200 uS
     break;
     
       
     case 3:             // Detta case ger tredje pulstid
     case 33:
          delvalue = VEVTAND_langd + delvalue;                    // föregående pulstid + föregående deltid läggs ihop
     break;
       
                                     
     case 4:             // Detta case ger fjärde pulstid
     case 34:
          delvalue = VEVTAND_langd + delvalue;                    // föregående pulstid + föregående deltid läggs ihop
     break; 
                             
       
     case 5:             // Detta case ger femte pulstid
     case 35:
          delvalue = VEVTAND_langd + delvalue;                   // föregående pulstid + föregående deltid läggs ihop
     break;
     
     
     case 6:              // Detta case ger sexte pulstid
     case 36:
           delvalue = VEVTAND_langd + delvalue;                   // föregående pulstid + föregående deltid läggs ihop
     break;
             
       
     case 7:             // Detta case ger sjunde pulstid
     case 37:     
           delvalue = VEVTAND_langd + delvalue;                   // föregående pulstid + föregående deltid läggs ihop
     break;
     
       
     case 8:             // Detta case ger motorns börvärde från gaspoten som blir lägsta och högsta varvtal
     case 38:
                         // och åttonde pulstid
           gas = constrain(gas,gaspotmin, gaspotmax);                         // först skall invärdet vara mellan min och max oavsett gaspotens verkliga värde (om utanför)       
           bduration = map (gas,gaspotmin, gaspotmax, lagstavarv, hogstavarv); // gör om gas analogvärde till lägsta/högsta uS värde
           delvalue = VEVTAND_langd + delvalue;                  // föregående pulstid + föregående deltid läggs ihop
     break;
   
       
     case 9:            // Detta case ger nionde pulstid
     case 39:
           delvalue = VEVTAND_langd + delvalue;                 // föregående pulstid + föregående deltid läggs ihop
     break;
     
       
     case 10:          // Detta case räknar ut tidsdiff per spridare plus systemspänningsdiff
     case 40:
       sprtroghetklar = sprtroghet + spridardiff - sprstartkorr;          // spridartröghet klart värde räknas ut här
                       // och ger motorns verkliga fart baserat på dom 11 första tänderna
       delvalue = VEVTAND_langd + delvalue;                                        // föregående pulstid + föregående deltid läggs ihop           
       mduration = delvalue/10;                                           // Motorns totala pulstid i mikrosek dividerat med 14 ger motorns duration vid drift (12 nu på prov)     
                      // och räknar ut skillnaden mellan är och börvärde - 1 = error
          error = (mduration / bduration)-1;
       if (error <=0.)                                                    // om error hamnar under noll
        {
         error = 0.;                                                      // förblir error 0 för att ej få minusvärden
        }
                 // här testas fasttid ut genom att gämföra vilken mduration som passar bäst.
          fasttid = (mduration < 1000) ? tid4 : (( mduration < 2400) ? tid3 : (( mduration < 3600 ) ? tid2 : tid1));  // nu dubblerat
     break;          // felet i uS mellan är och börvärde för motorns duration (varvtal)
                       
   
     case 11:        // Detta case för insprutningsfördröjning i gånger, ställs högst upp
     case 41:               
       starttandf = (mduration * korrfaktor) /tidigasteinspr;            // starttandf, ett flyt-tal = motorns duration x korrektionstal/ minsta duration.
       if (starttandf >= senasteinspr)                                   // om fördröjning över målvärdet, som vid tex startvarv
        {                 
         starttandf = senasteinspr;                                      // blir det målvärdet ändå
        }
     break;
     
 
     case 12:       // Detta case ger förtändningen
     case 42:
        ondelay = (mduration * starttandf);                                 // tillslagsfördröjning = motorns duration * starttandsfördröjning (decimaltal)
                                                                            // Ondelay uS = mduration uS * starttandf i decimalform
       if((mduration > omslagstartdrift) && (mduration < omslagmillimicro)) // delta2 skall vara aktiv mellan 2500 us ner till 1200 uS
         {
          delta2 = lagmangd * mduration;                                                                             
         }
       else
         {
          delta2 = 0;
         }
     break;       
     
     case 13:               // Här räknas effektregleringen ut genom hela registret från 450 rpm och uppåt
     case 43:
     if(mduration <=omslagstartdrift)                                      // Om/när motorn går över 450 rpm
     {
      aggrfaktor = faktor/mduration;                                       // Här räknas aggresionsfaktorn ut med hänsyn av en gångerfaktor/ motorns duration. (varvtal)
      if(aggrfaktor < minstaAggrFaktor)                                    // om aggresionsfaktorn blir mindre än minsta aggresionsfaktor
      {
        aggrfaktor = minstaAggrFaktor;                                     // så blir ändå aggresionsfaktorn den förutbestämda agresionsfaktorn.                                             
      }
      delta = aggrfaktor * mduration * error;                              // Här räknas delta ut med hänsyn till agresinsfaktorn, motorns duration och gasreglägets värde
     }       
     break;

     case 14:            // Detta case ger mjukstarten
     case 44:
      if (mduration >= omslagstartdrift)                                    // Vid lite över startfart  mellan 200 RPM till ca 450 RPM
      {
       delta = lagmangd * mduration;                                        // blir det mjukstart som justeras via lågmängd             
      }
               // och absolut längsta insprutningstid
     if (delta + ondelay >= totaltid * mduration)                           // om delta och ondelay i uS blir mer än totaltid
      {       // så justeras endast delta ner
       delta = (totaltid * mduration)-ondelay;                              // Absolut max insprutningstid (delta),
      }       // denna justering gäller för max insprutnings-"fönster"
     break;

     case 15:   // Detta case ger olika förtändning för start och drift
     case 45:
         if (mduration < omslagstartdrift)                                  // går motorn över driftfart?
          {
           senasteinspr = senasteinsprdrift;                           // i så fall läggs förtändning drift (normalfallet)
          }
        else
         {
         // Annars förtändning start                                        // läser av A1 motortemp
         }
     break;
 //------------------------------------------------------------------------------------- case 16, insprutningsfasen-----------------------------------------------------------------   
     case 16:    // Detta case är insprutningsfasen "spridar-on-off-mode"
     case 46:
     
      if (mduration >=omslagmillimicro)       // Om motorns duration är mer än xx uS. (från 131 till 203 RPM räknas alla spridarvärden i mS) 2500 = 203 RPM
       {                                      // går tiden över från uS till mS.
        ondelay = ondelay/1000;               // Ondelay uS blir mS.
        delta = delta/1000;                   // Delta uS blir mS.

                // avgör om tillräcklig fart är uppnådd för motorstart                   
         if(mduration >= minfart)                // motorn måste upp i x fart för att få bränsle, (minfart i uS)
          {                         
          delta = 0;                             // vid underfart, delta(insprutningstid)nollas
          }
                // och startmängden vid motorstart
          if ((delta * 4)>= startmangd)          // här ställs startmängden in 
           {
           delta = startmangd;                   // så det blir rätt startmängd/slag (5 = 0,75 tänder = 4,5 vevgrader)
           }
           delay(ondelay);                       // Fördröjer starttiden x antal mS beroende på varvtalet (mdurationen)
           digitalWrite (sprpins[visare],HIGH);  // Spridarpinne hög,insprutning börjar. spridare x strömsätts [visare 8,9,10 eller 11].
           digitalWrite(sprControl, HIGH);       // Kontrollpinne som blir hög vid varje insprutningstillfälle.
          // Serial.println(delta);
           delay(delta);                         // Här läggs insprutningstiden in som sen fördröjer processorn i delta mS
           digitalWrite (sprpins[visare],LOW);   // Spridarpinne låg,insprutning avslutad spridare x stängs av  [visare 8,9,10 eller 11].
           digitalWrite (sprControl, LOW);       // Kontrollpinne som går tillbaka till låg efter varje insprutningstillfälle.
           ondelay = ondelay*1000;               // Ondelay mS blir uS.
           delta = delta*1000;
       }         // Detta paket används vid låga farter såsom start/lågvarv < 203 RPM
     //---------------------------------------------------------------------------------------------------------------------------- 
    else        // Eller om mduration är mindre än 2500 uS. (> 203 RPM)
       {
         if (delta > utanvarde)                 // Delta under utanvärde uS har inget värde
          {
           delta = delta + sprtroghetklar;      // Delta blir  delta + trögheten i spridaren (ca 200-500 uS)som tröghetskompensation
          }
          ondelay = ondelay - sprtroghetklar;   // tidigarelägger insprutningstart med hänsyn till spridartrögheten
          delayMicroseconds(ondelay);           // Fördröjer starttiden i ondelay uS beroende på varvtalet (mdurationen)
          digitalWrite (sprpins[visare],HIGH);  // Insprutning börjar. spridare x strömsätts [visare 11,10,9 eller 8].
          digitalWrite(sprControl, HIGH);       // Kontrollpinne som blir hög vid varje insprutningstillfälle.
         // Serial.print(delta);
         // Serial.print(" ");
         // Serial.println(delta2);
          delayMicroseconds(delta);             // Här läggs insprutningstiden in som sen fördröjer processorn i delta uS
          delayMicroseconds(delta2);            // Här läggs en extra insprutningstid in som bara gäller mellan 203-450 rpm
          digitalWrite (sprpins[visare],LOW);   // Spridarpinne låg,insprutning avslutad spridare x stängs av [visare 8,9,10 eller 11]
          digitalWrite (sprControl, LOW);       // Kontrollpinne som går tillbaka till låg efter varje insprutningstillfälle.
       }                                //Detta paket används vid varv (203 -> RPM = nästan alltid, förutom vid motorstart)
       visare ++;
     if (visare > 3)                            // när fjärde pinnen är nådd börjar den om igen
         {
         visare = 0;                            // spridarpinne 0 är igång igen (0 = D11)
         }
        // Serial.println(visare);
     break;      // Detta paket tar 1 till 6 tänder att genomföra beroende på varvtal och belastning
//-------------------------------------------------------------------- case 16, insprutningsfasen avslutad-------------------------------------------------------------------------


               // Här läses alla analoga signaler max 2 per gång av max 8 st totalt (A0 till A7)
     case 26:                                 // är mellan  tand 17 och 23
     case 56:
          switch (analogval)
     {
        case 0:   
           gas = analogRead(A0)>>2;           // analogingång för gasreglage 0 till 255( skiftad 2 gånger)
           // tom
        break; 

        case 1:
           battVolt = analogRead(A7);         // analogingång som läser ECU:ns systemspänning
           // tom
        break;

        case 2:
           gas = analogRead(A0)>>2;           // analogingång för gasreglage 0 till 255( skiftad 2 gånger)
           // tom                             
        break;
       
        case 3:
            fart_flakt = analogRead(A0)>>2;    // analogingång för gasreglagefläkt 0 till 255( skiftad 2 gånger)
            fart_flakt = fart_flakt + grundfart;// Här läggs en grundfart till för att säkerställa fläktfunktion lågfart.
        break;

        case 4:
           gas = analogRead(A0)>>2;             // analogingång för gasreglage 0 till 255( skiftad 2 gånger)
           // tom
        break;

        case 5:
           // tom
           // tom
        break;                               
     }
     
     analogval ++;                              // räkna upp analogval 1 steg   
       if (analogval > 5)                       // när analogval har blivit 5 så
        {
         analogval = 0;                         // resettas analogval till 0 igen
        }   
    break;     // analalogRead tar ca 120 uS att läsa = 1-2 tänder vid fullvarv
  }                                            // nu är alla switch-case lästa
     if(fart_flakt >= flaktfart)           // om gasfläktens fart ät mer än 255
         {
          fart_flakt = flaktfart;              // så förblir gasfläkt max 255
         }
         analogWrite(elflakt,fart_flakt );     // pulsbreddsmodulerar ut fläktfart mellan grundfart och maxfart (980 hz PWM)
  }
 //-------------------------------------- Nedan är för att leta upp tandluckan, räkna upp tandräknaren,reseta tandräknaren, bestämma motorns duration (varvtal)--------------------------
           
     
 }
  void VEV_pulse()                          //
 {
  long thisLength = micros();              // tar ett ögonblicksvärde på microsekunderräknaren
  caseRead = 1;                            // sätter en flagga till case read
  prev_langd = VEVTAND_langd;              // nuvarande vevtands längd läggs in som föregående vevtandslängd (döper om)
 
  VEVTAND_langd = thisLength-VEVTAND_start;  // Längden på nuvarande lucka hamnar i variabeln VEVTAND_langd
  VEVTAND_start = thisLength;                // Börja mätning av lucka
   tand++;                                   // tandräknaren räknar upp en tand
   //Serial.println(tand);
   if(VEVTAND_langd > prev_langd + fasttid)     // OM nyaste vevtands längd är längre än föregåendes + fasttid
    {                                           // då är luckan hittad
    digitalWrite(pulsutpin, HIGH);              // Då går utpin hög
    tand = 0;                                   // och tandräknaren resetas till 0 (början på tandräkningen)
   
                  // Denna if-sats är bara sann varje halv-varv vid luckan
    }
  if(VEVTAND_langd < prev_langd - fasttid)      // OM nyaste vevtands längd är kortare än föregående -fasttid
   {                                      // då är luckan slut
   digitalWrite(pulsutpin, LOW);               // och utpin blir låg igen.
   }
 
 }
 //--------------------------------------------Här slutar den Interruptstyrda delen------------------------------------------------------------------------------------------
       
//-------------------------------------------------slut loop-----------------------------------------------------------------------------------------------------------------------       
                                               

Författare:  Janson1 [ 21.19 2019-09-24 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Nästa kanske konstig/dum fråga men först lite bakgrund: Av en händelse så sprang jag på en ny NANO med efternamn Every
Den har en nyare processor Atmega 4809, en 8 bitars med mer timers (bla.) Jag har nu fått hem den, provat mitt ECU-program men det blir nåt slags fenomen, jag vet inte än om det påverkar motorn gång eller ej då jag hittills bara kört hemma på kammaren. Nu till min fråga som fortfarande gäller timers/prescalers: Arduinos IDE, är det speciellt anpassat för Atmega328 och 2560 serien? Jag tycker att den här 328 klarar alla mina behov på ECU:n men känner att jag kanske behöver lite mer kräm, nån mer PWM-utgång, nån mer analogingång etc. Och så fort jag provat en annan processorfamilj, (STM32, Atmega 32) så har mina fungerande funktioner antingen gett upp helt eller fått en massa bieffekter... Så, är IDE:n gjord speciellt för 328:an (2560)???
För varje gång jag provat en annan processorfamilj har det blivit skit!

Författare:  ToPNoTCH [ 21.57 2019-09-24 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Jag tror jag berört detta tidigare.

Det enkla svaret är ja.
Porteringar till andra processorer utöver de "officiella" är oftast egna opensource initiativ.
Därav är vissa porteringar bättre än andra.

Arduino utvecklades ursprungligen för 328 och 2560 som med dagens mått är jäkligt omoderna.
Detta gör att den som porterar måste ta ställning till om att behålla kompatibilitet eller tillföra kommandon för att utnyttja processorn är viktigast.

Ett bra exempel är ESP32 där man lagt till ledc kommandot för att styra den interna LED-Controllern.
Kod med det kommandot går ju inte att köra på annan processor trots att det är "Arduino språk".

Här har man alltså gjort ett val att tillföra processor unik funktionalitet på bekostnad av kompatibilitet.
Andra som porterar kan ha en mer stringent syn för att alla befintlig kod som figurerar skall funka direkt.

Om du ovanpå detta faktum lägger till alla bibliotek som i sin tur fungerar olika (eller inte fungerar alls) med andra processorer, så är komplexiteten och förvirringen ett faktum.

Jag vet att talat om att växla till standard C och jag vill inte verka tjatig. Men det är enligt min uppfattning nära på nödvändigt om du vill nyttja en modern processor fullt ut och verkligen själv förstå hur hela ditt program fungerar.
Om din hobby är ECU och kodningen nödvändigt ont så fattar jag din tvekan. Men om du tycker kodningen är intressant och funderar på fler MCU projekt framöver tycker jag du borde smyga igång lite med C och känna dig för.
Tröskeln kanske inte är så stor som den känns.

Fick för mig att du hade en "Blue Pill" liggandes. Bara att ladda ner Atollic (gratis) och skaffa en St Link programmerare så är du igång.

Författare:  Janson1 [ 05.42 2019-09-25 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Ja detta är väl egentligen svar på min fråga. Jag har Atollic som jag så smått börjat titta på, även ett antal "Blue Pill" moduler.
Till dom har jag i dag en omvandlare från USB till ja, seriellt snitt av något slag, det funkar att programmera med i alla fall. Duger detta ihop med Atollic också, eller måste det vara en ST-Link?

Författare:  ktm_micke [ 12.57 2019-09-26 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Har du tittat på Teenesy jag ska bygga en styrning till en BMW DCT låda o hade först tänkt att ha en arduino men så hittade jag dessa har tänkt att göra ett kort som man dockar på denna blir nog en Teenesy 3.6 en nere i lådan o en inne i bilen med can bus communikation den i lådan läser av växlingsläge (analog HAL) och varvtal skickar till den inne i bilen där den styr solenoiderna totalt 10 st varav 6 st PWM styrda anledningen till att jag måste ha en i lådan med är att jag ska använda original kontakt på lådan o den har bara 13 kablar.
https://www.pjrc.com/teensy/techspecs.html

Författare:  Janson1 [ 19.53 2019-09-27 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Just denna Teenesy har jag inte tittat på. MEN, jag misstänker att Arduinos kompilator inte är den bästa för denna processorn heller... Jag är inte riktigt beredd på att skippa Arduinos IDE så kanske jag gör ett försök? Ktm_micke: Skall du programmera i Arduino eller nåt annan IDE?

Författare:  ktm_micke [ 08.11 2019-09-28 ]
Inläggsrubrik:  Re: Skillnader i timers, prescalers på Atmega och STM32

Ang IDE vet jag inte ännu lutar dock åt arduino

Alla tidsangivelser är UTC + 1 timme
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/