Dimma med Nexa och en Arduino, *nya bekymmer*

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
hanpa
Utsparkad, på semester
Inlägg: 639
Blev medlem: 22 november 2016, 21:54:43
Ort: Hemort

Re: Dimma med Nexa och en Arduino, lite problem..

Inlägg av hanpa »

State är ju vilket läge man befinner sig i programmet, alltså som säger vad som ska ske just nu i huvudloopen. Jag kanske missuppfattat uppgiften men som jag fattat det ska man antingen
- Dimma upp eller ner, tills man trycker ON eller OFF (state DIMMING)
- Stänga av (state OFF)
- Låta det lysa med den nivå man hade när man slutade dimma (state ON)

Det enda man man behöver göra i huvudloopen är då att kolla på vilket state man har och göra något av detta.

Kommandon från fjärren är inte direktkopplade till staten, men sätter state.

Så här tolkade jag det som står, men kan förstås vara missuppfattat.

Om det kommer kommando ON:
- Börja dimma om state var OFF eller ON, dvs sätt state DIMMING
- Sluta dimma om state var DIMMING, dvs sätt state ON

Om det kommer kommando OFF:
- Sätt state OFF

Kanske blev det förvirrat för att ett av staten är ON och det förväxlas med vad man trycker på fjärren. Men kalla det något annat då typ, PAUSE. Staten blir då OFF (släckt), DIMMING (dimma upp/ner) och PAUSE (gör inget speciellt, dvs låt det lysa som det gjorde innan man slutade dimma)

Alltså:
enum dimmerStates {
OFF,
DIMMING,
PAUSE
};

dimmerStates dimmerState = OFF;
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Dimma med Nexa och en Arduino, lite problem..

Inlägg av Magnus_K »

Tack för en mycket bra förklaring hanpa. Det var en missförstånd mellan state och fysisk knapptryckning.
Nu har jag aldrig vad jag kommer ihåg) använt enums men skrev om koden som jag misstänker du menar. Hur nära är vi på en skala?

@Jonaz:
Det blir säkert lite kompileringsfel och annat men testa gärna koden om du vill. Om vi till slut lyckas få ihop det här så det fungerar för dig, så ska jag göra en sammanfattning om ändringar från ditt original. Det viktigaste är att du vet vad som händer.

Kod: Markera allt

#include <NewRemoteReceiver.h>
     
boolean codeLearned = false;
unsigned long learnedAddress;
unsigned short learnedUnit;
const int ledPin = 9;       // the pin that the LED is attached to

enum dimmerStates {
OFF,
DIMMING,
PAUSE
};

dimmerStates dimmerState = OFF;

 
void setup() {
  // LED-pin as output
  pinMode(9, OUTPUT);
  pinMode(13, OUTPUT); // Only for debugging
  // Init a new receiver on interrupt pin 0, minimal 2 identical repeats, and callback set to processCode.
  NewRemoteReceiver::init(0, 2, processCode);
}
 

void loop() {
  // Blink led until a code has been learned
  if (!codeLearned) {
    digitalWrite(13, HIGH);
    delay(500);
    digitalWrite(13, LOW);
    delay(500);
  }
  if( (dimmerState == PAUSE) || (dimmerState == DIMMING) ){
    for (int i = 0; i < 255; i++){
      if(dimmerState == PAUSE){
        i--;
      }
      analogWrite(ledPin, i);
      delay(5);             // Only for fade effect
    }
    for (int i = 255; i > 0; i--){
      if(dimmerState == PAUSE){
        i++;
      }
      analogWrite(ledPin, i);
      delay(5);           // Only for fade effect
    }
  }
  if(dimmerState == OFF){
    analogWrite(ledPin, 0);  
  }
}


// Callback function is called only when a valid code is received.
void processCode(NewRemoteCode receivedCode) {
  // A code has been received.
  // Do we already know the code?
  if (!codeLearned) {
    // No! Let's learn the received code.
    learnedAddress = receivedCode.address;
    learnedUnit = receivedCode.unit;
    codeLearned = true; 
  } else {
    // Yes! 
    // Is the received code identical to the learned code?
    if (receivedCode.address == learnedAddress && receivedCode.unit == learnedUnit) {
      // Yes!   
      // switchType == 1 means on, switchType == 0 means off.
      if (receivedCode.switchType == 1) {
        if( (dimmerState == PAUSE) || (dimmerState == OFF) ) {
          dimmerState = DIMMING;       
        } else {
          dimmerState = PAUSE;
        }
        digitalWrite(13, HIGH);
      } else if (receivedCode.switchType == 0) {
        dimmerState = OFF;
        digitalWrite(13, LOW);
      }
    }
  }
}
Senast redigerad av Magnus_K 21 januari 2017, 20:45:48, redigerad totalt 1 gång.
Användarvisningsbild
hanpa
Utsparkad, på semester
Inlägg: 639
Blev medlem: 22 november 2016, 21:54:43
Ort: Hemort

Re: Dimma med Nexa och en Arduino, lite problem..

Inlägg av hanpa »

Rent principiellt är det rätt men jag förstår inte det som görs i PAUSE, man borde inte behöva köra några loopar då eftersom man inte ska dimma något. Är det inte tanken att då man tryckt ON igen efter att den dimmat upp/ned att man bara ska stanna på den ljusstyrka man har? I så fall borde man väl inte göra något alls i state PAUSE.

Angående enum så det en snygg lösning för tillstånd, speciellt om man har fler än två tillstånd (boolean kan ju duga om det är två).

Man göra på fula sätt också och använda int och sätta 0, 1, 2 osv. men det blir inte lika snyggt.
En enum är faktiskt en int i detta fall med värdena 0, 1, 2 men det blir mycket tydligare att sätta och jämföra mot PAUSE etc. i koden än att använda siffran 2.

Man kan också använda strängar med "OFF", "PAUSE" etc. och kolla deras värden i if-satsen.

Men du är helt klart på rätt spår, enum det snyggaste även om jag fuskar själv ibland...

Den här lär inte funka,

Kod: Markera allt

if(dimmerState == (PAUSE || OFF))
bör vara

Kod: Markera allt

if( (dimmerState == PAUSE) || (dimmerState == OFF) )
Senast redigerad av hanpa 21 januari 2017, 20:41:33, redigerad totalt 1 gång.
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Dimma med Nexa och en Arduino, lite problem..

Inlägg av Magnus_K »

Det här är intressant.
Den ska alltså dimma upp/ner om och om igen när det är state DIMMING. När detta sedan ändras till PAUSE så ska dimmningen stanna precis där den är, men alltså fortsätta lysa med den styrkan som den har.
Om man då alltså är mitt i en for-loop och state ändras från DIMMING till PAUSE, hur får man den att avbryta loopen där den är?

EDIT: Tackar för tipset med if-satsen. Redigerade det i koden ovan.
Användarvisningsbild
hanpa
Utsparkad, på semester
Inlägg: 639
Blev medlem: 22 november 2016, 21:54:43
Ort: Hemort

Re: Dimma med Nexa och en Arduino, lite problem..

Inlägg av hanpa »

Enklast är att ta bort looparna.

I OFF stänger du bara av.
I PAUSE gör du inget alls.
I DIMMING behöver du hålla reda på om du dimmar upp eller ner och så gör du en enda ändring och lägger in din delay. När du når ändlägena så byter du riktning.

Exempelvis två globala variabler:

Kod: Markera allt

int ledValue = 0;
int dimChange = 1;
Och i state DIMMING i loop()

Kod: Markera allt

ledValue = ledValue + dimChange;
if ( (ledValue > 255) || (ledValue < 0) ) {
 dimChange = -dimChange;  // byt håll
 ledValue = ledValue + dimChange;  // backa tillbaka ett snäpp...
}
analogWrite(ledPin, ledValue);



delay(5)
//Slut på loop()
Huvudloopen kommer att köras hela tiden och så länge state är kvar i DIMMING så kommer värdet att räkna upp eller ner och byta i ändlägena. Som jag skrev kommer 255 resp. 0 sättas två gånger i rad i ändlägena men det är inget man märker. Går ju att göra koden mer komplex om man vill.

Delay(5) lägger du bara sist i loop(), efter att du kollat allt det andra.
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Dimma med Nexa och en Arduino, lite problem..

Inlägg av Magnus_K »

Väldigt snällt av dig hanpa. :tumupp:
Jag överlåter det sista inlägget till TS för nu bör det finnas tillräckligt för att ro det här i land.
Användarvisningsbild
Jonaz
Inlägg: 2326
Blev medlem: 4 november 2003, 22:06:33
Ort: Huddinge

Re: Dimma med Nexa och en Arduino, lite problem..

Inlägg av Jonaz »

Tack, men hängde jag inte riktigt med, var skulle jag lägga in
ledValue = ledValue + dimChange;
if ( (ledValue > 255) || (ledValue < 0) ) {
dimChange = -dimChange; // byt håll
ledValue = ledValue + dimChange; // backa tillbaka ett snäpp...
}
analogWrite(ledPin, ledValue);
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Dimma med Nexa och en Arduino, lite problem..

Inlägg av Magnus_K »

Något liknande nedan borde fungera.
Om det gör det så kanske det blir lite snyggare med en switch() istället för 3 if-satser efter varandra, men det behöver inte göras än.

Kod: Markera allt

#include <NewRemoteReceiver.h>
     
boolean codeLearned = false;
unsigned long learnedAddress;
unsigned short learnedUnit;
int ledValue = 0;
int dimChange = 1;
const int ledPin = 9;       // the pin that the LED is attached to

enum dimmerStates {
OFF,
DIMMING,
PAUSE
};

dimmerStates dimmerState = OFF;

 
void setup() {
  // LED-pin as output
  pinMode(9, OUTPUT);
  pinMode(13, OUTPUT); // Only for debugging
  // Init a new receiver on interrupt pin 0, minimal 2 identical repeats, and callback set to processCode.
  NewRemoteReceiver::init(0, 2, processCode);
}
 

void loop() {
  // Blink led until a code has been learned
  if (!codeLearned) {
    digitalWrite(13, HIGH);
    delay(500);
    digitalWrite(13, LOW);
    delay(500);
  }
  if(dimmerState == OFF){
    analogWrite(ledPin, 0);
  }
  if(dimmerState == PAUSE){
  }
  if(dimmerState == DIMMING){
    ledValue = ledValue + dimChange;
    if ( (ledValue > 255) || (ledValue < 0) ) {
      dimChange = -dimChange;  // byt håll
      ledValue = ledValue + dimChange;  // backa tillbaka ett snäpp...
    }
  analogWrite(ledPin, ledValue);
  }
  delay(5)
}


// Callback function is called only when a valid code is received.
void processCode(NewRemoteCode receivedCode) {
  // A code has been received.
  // Do we already know the code?
  if (!codeLearned) {
    // No! Let's learn the received code.
    learnedAddress = receivedCode.address;
    learnedUnit = receivedCode.unit;
    codeLearned = true; 
  } else {
    // Yes! 
    // Is the received code identical to the learned code?
    if (receivedCode.address == learnedAddress && receivedCode.unit == learnedUnit) {
      // Yes!   
      // switchType == 1 means on, switchType == 0 means off.
      if (receivedCode.switchType == 1) {
        if( (dimmerState == PAUSE) || (dimmerState == OFF) ) {
          dimmerState = DIMMING;       
        } else {
          dimmerState = PAUSE;
        }
        digitalWrite(13, HIGH);
      } else if (receivedCode.switchType == 0) {
        dimmerState = OFF;
        digitalWrite(13, LOW);
      }
    }
  }
}
Användarvisningsbild
Jonaz
Inlägg: 2326
Blev medlem: 4 november 2003, 22:06:33
Ort: Huddinge

Re: Dimma med Nexa och en Arduino, lite problem..

Inlägg av Jonaz »

:bravo: :bravo: :bravo:
:tårta:

Det funkar nästan, nu dimrar den visserligen inte ner till 0 när man trycker på off, utan det är helt av direkt, och från av så påbörjas en ny dimning som man får stoppa.
Men jag skall undersöka lite, tror jag kanske kan lösa det själv.

Återkommer.
Senast redigerad av Jonaz 22 januari 2017, 01:45:32, redigerad totalt 1 gång.
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Dimma med Nexa och en Arduino, lite problem..

Inlägg av Magnus_K »

Bra, bra. :)
Då ska vi först försöka få till att den dimmar ner till 0 vid OFF. Det borde gå genom att lägga till en liten nedräknare enligt nedan, istället för att sätta den till 0 direkt.

Byt ut:

Kod: Markera allt

if(dimmerState == OFF){
    analogWrite(ledPin, 0);
  }
till:

Kod: Markera allt

if(dimmerState == OFF){
    if(ledvalue > 0){
      ledvalue--; 
    }
  }
Användarvisningsbild
Jonaz
Inlägg: 2326
Blev medlem: 4 november 2003, 22:06:33
Ort: Huddinge

Re: Dimma med Nexa och en Arduino, lite problem..

Inlägg av Jonaz »

Japp det gjorde skillnad, var faktiskt inne på samma spår, fast inte i närheten ändå.

Har försökt så den kommer i håg senaste värdet innan man gick till off, från pause, dvs vill att den skall gå från off till senaste pause värdet.
Skall man göra någon ny variant med int lastledValue = 0; eller lägga till något i enum dimmerStates?
Stort tack för hjälpen så länge.

@Magnus_KJag förstår nog det mesta vad som händer i koden så du behöver inte skriva vad som ändrades från mitt första försök.
Sen att man förstår och kan skriva det är ju en stor skillnad.. :cry:
Användarvisningsbild
hanpa
Utsparkad, på semester
Inlägg: 639
Blev medlem: 22 november 2016, 21:54:43
Ort: Hemort

Re: Dimma med Nexa och en Arduino, lite problem..

Inlägg av hanpa »

Nu börjar det se bra ut!

Den tomma if-satsen för PAUSE kan man ju ersätta med en kommentar, bara för att visa att man faktiskt tänkt på fallet. Switch går ju också bra men är det få fall så funkar if. Det är lite en smaksak hur man gör, det viktiga är att man tänkt på alla fall. Det fina med att använda enum är att man ser tydligt vilka fall det finns.

I just detta fall vill man tydligen ha neddimmning då man stänger av, det hade jag inte observerat. Ska man gå vidare på state och enum så är det rimligt att föra in ett eget state för detta, typ DIMMING_TO_OFF eller liknande. Då kan man skilja på att programmet (och verkligheten) håller på att dimma ner till helt av (DIMMING_TO_OFF), eller helt enkelt bara är i helt avstängt läge tills vidare (OFF).

Med detta extra tillstånd så sätter man DIMMING_TO_OFF när man tar emot kommandot från Nexa.
Sen räknar man ner osv och när man kommit ned till noll sätter man istället state till OFF i loop(), alltså inte från koden som hanterar kommandona från Nexa, den delen har inget med detta att göra.

Funkar ju att räkna ner i state OFF men det blir snyggare med eget state. Att dimma i läget OFF är principiellt fel, OFF borde inte vara något annat än helt av...

Om man ska lösa den här typen av uppgift så är det att rekommendera att börja med att titta på vad programmet ska göra och lista detta. Kan man sen översätta detta till state och övergångar mellan dessa så blir koden enkel och tydlig.
- Dimma upp/ner
- Stanna på senaste värdet man dimmat till
- Dimma ner till helt avstängt
- Ligga kvar i avstängt läge

Sen handlar det bara om att fundera på vilket state man startar i (antagligen avstängt läge) , hur man ska växla mellan staten, och vad man ska döpa staten till (ju bättre namn man väljer, desto enklare är det att förstå koden). Man kan ha egna state för DIMMING_UP, DIMMING_DOWN om man vill och så byter man i loop() mellan dessa i ändlägena. Dock måste man ju komma ihåg var man var då man går från PAUSE och tillbaka, men då kan man ju välja detta baserat på dimChange. Eller så skippar man dimChange och istället har en variabel som heter lastDimmingState och sätter den till DIMMING_UP eller DIMMING_DOWN. I loop() låter man sen state DIMMING_UP eller DIMMING_DOWN avgöra om man ska öka eller minska.

Att komma ihåg var den var i PAUSE senast då man går tillbaka från OFF till DIMMING borde lösa sig automatiskt med globala varaiblerna ledValue och dimChange, deras värden ligger ju kvar. Om man accepterar att man även minns dimmningsriktningen så behöver man inte göra något speciellt men om man vill att den alltid ska gå uppåt i det läget så är det ju bara att tilldela dimChange till 1 då man går från OFF till DIMMING. Jag kan tycka att det är naturligt att alltid gå i en viss riktning då och uppåt är det naturliga. Det kan ju ha gått flera dagar sedan man stängde av och då är det rimligt att alltid gå i en viss riktning istället för att man ska bli överraskad och det kanske passar ibland och ibland inte. Man kan förstås sätta ett tidskriterium och minnas riktningen inom en viss tid bara, annars välja upp eller ned oavsett vad man hade senast.
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Dimma med Nexa och en Arduino, lite problem..

Inlägg av Magnus_K »

Det för alltid något gott med sig genom att hjälpa andra.
Du har helt ändrat mitt tänk hanpa, och det är jag väldigt tacksam över. Det är kodplanering enligt ovan som gör att man inte kör fast så lätt och koden blir lättare att läsa/följa.
Ska faktiskt prova att skriva om ett av mina projekt enligt din STATE-metod. Projektet har legat vilande i 1 år pga att jag inte får ihop koden. Får se hur det går. :tumupp:

@Jonaz:
Nu är det självklart upp till dig men jag röstar absolut för att lägga till en ny state för när den dimmar ner, och sedan avslutar med att sätta state OFF.
Läs igenom hanpa's inlägg ett par gånger och gör något försök. Får du inte ihop det så kan jag försöka hjälpa dig senare i kväll.
Användarvisningsbild
Jonaz
Inlägg: 2326
Blev medlem: 4 november 2003, 22:06:33
Ort: Huddinge

Re: Dimma med Nexa och en Arduino, lite problem..

Inlägg av Jonaz »

Japp skall läsa igenom ett par gånger och försöka.
Tack så länge!
Användarvisningsbild
hanpa
Utsparkad, på semester
Inlägg: 639
Blev medlem: 22 november 2016, 21:54:43
Ort: Hemort

Re: Dimma med Nexa och en Arduino, lite problem..

Inlägg av hanpa »

Magnus_K skrev:Det för alltid något gott med sig genom att hjälpa andra.
Du har helt ändrat mitt tänk hanpa, och det är jag väldigt tacksam över. Det är kodplanering enligt ovan som gör att man inte kör fast så lätt och koden blir lättare att läsa/följa.
Ska faktiskt prova att skriva om ett av mina projekt enligt din STATE-metod. Projektet har legat vilande i 1 år pga att jag inte får ihop koden. Får se hur det går. :tumupp:

@Jonaz:
Nu är det självklart upp till dig men jag röstar absolut för att lägga till en ny state för när den dimmar ner, och sedan avslutar med att sätta state OFF.
Läs igenom hanpa's inlägg ett par gånger och gör något försök. Får du inte ihop det så kan jag försöka hjälpa dig senare i kväll.
Tack, roligt att kunna hjälpa till. Jag fulhackar själv kod i många fall men jag har grunden i bakhuvudet då jag jobbat med programmering i många år. Om man hamnar i läget att man inte vet hur man ska få det att funka så behöver man strukturera upp det. Kanske kasta koden och börja om från början.

Andra sätt att få ordning på det är att lägga in loggutskrifter så att man ser vad som händer, då förstår man vad det är som inte funkar som det ska. Sen ytterligare en grej, när man fått det att funka, ta en vända och snygga till, ta bort oanvända variabler, döp om variablerna till något bättre om de är av typen i, v, etc. och inte säger något om vad det betyder. Lägg in några kommentarer. Gör några functions om man har duplicerad kod eller att det är svårläst för att det är många kodrader. Ofta behöver man gå in senare i programmet och det är banne mig inte lätt att förstå vid ett senare tillfälle om man hackat ihop något som fungerar men man vet inte varför...
Skriv svar