Vart i koden skriver jag fel?

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Användarvisningsbild
arvidb
Inlägg: 4537
Blev medlem: 8 maj 2004, 12:56:24
Ort: Stockholm

Re: Vart i koden skriver jag fel?

Inlägg av arvidb »

Sant.

Hur är det fosfor, blir du nå klokare av mitt kodexempel?

Sannolikt behöver du plocka ut alla digitalRead() och digitalWrite() från update_lcd() och placera dem i en egen funktion som anropas från loop() för att det hela ska fungera korrekt. D.v.s. skilja på koden som läser/styr status och på koden som uppdaterar lcdn.
Användarvisningsbild
adent
Inlägg: 4094
Blev medlem: 27 november 2008, 22:56:23
Ort: Utanför Jönköping
Kontakt:

Re: Vart i koden skriver jag fel?

Inlägg av adent »

Det finns en anledning till att jag har en röd stämpel som det står "INDENTERA!" på som gjorde rättandet av labbar och tentor lite roligare när jag var labbhandledare/lärare på högskolan.

Oindenterad eller värre - felindenterad kod blir väldigt svårläst, så pass svårläst att man med lätthet lurar sig själv.

MVH: Mikael
Användarvisningsbild
lillahuset
Gått bort
Inlägg: 13969
Blev medlem: 3 juli 2008, 08:13:14
Ort: Norrköping

Re: Vart i koden skriver jag fel?

Inlägg av lillahuset »

:tumupp:
Användarvisningsbild
fosfor
Inlägg: 453
Blev medlem: 13 februari 2013, 05:43:15
Kontakt:

Re: Vart i koden skriver jag fel?

Inlägg av fosfor »

Hoy!

Tillbaka nu, haft lite andra projekt senaste dagarna.
Så nu ska jag försöka lösa och snygga till koden igen efter era visa råd och tips här nu under dagen :)
Användarvisningsbild
fosfor
Inlägg: 453
Blev medlem: 13 februari 2013, 05:43:15
Kontakt:

Re: Vart i koden skriver jag fel?

Inlägg av fosfor »

Hej arvidb

Tack för svar, det ser ut som att du skrivit något viktigt, och jag vill gärna veta mer. :tumupp:
Jag ska framhäva att jag är helt ny på detta med Arduino programmering. :shock:
Så jag har lite svårt att hänga med på den text (om enum osv) som du la till/ändrade på min text.
:shock:
Jag ser att mycket har flyttats ut från void loopen, verkar vettigt.
Ska bara försöka få mitt huvud runt hur koden fungerar.

Om du har möjlighet så skulle jag jättegärna läsa en extra beskrivning som förklarar lite mer vad som är vad och varför. :tumupp: :tumupp:
Användarvisningsbild
fosfor
Inlägg: 453
Blev medlem: 13 februari 2013, 05:43:15
Kontakt:

Re: Vart i koden skriver jag fel?

Inlägg av fosfor »

Såhär ser kalaset ut just nu. :shock:

Funktionen är följande:
Två knappar fungerar att använda, de snurrar motorn åt ena eller andra hållet sålänge en av dom är intryckta. Stannar alltså när man släpper.
Om sensorerna (de som syns nära skärmen) täcks så stoppar den motorn och ger en liten pipsignal.
Detta är för att hindra motorn snurra för långt åt ena eller andra hållet. Men man kan köra åt motsatta hållet som blivit stoppat.
På displayen visas pulser, går även åt minushållet.
Den visar även texten Down eller Up på LCD beroende på vilket håll motorn går när man trycker in en knapp, och STOP när en sensor täcks åt något av hållen.

Framtida ändringar, när väl koden ser bra ut och förhoppningsvis ingen text flimrar på skärmen etc.
Är att ha två knappar för långsam upp och ner, samt att kunna spara en position som den sen stannar vid när den passerar den positionen.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Senast redigerad av fosfor 30 januari 2018, 09:04:45, redigerad totalt 1 gång.
Användarvisningsbild
arvidb
Inlägg: 4537
Blev medlem: 8 maj 2004, 12:56:24
Ort: Stockholm

Re: Vart i koden skriver jag fel?

Inlägg av arvidb »

Detta med enum är mest ett sätt att göra koden mer läslig. I princip så är

Kod: Markera allt

enum state {
	STATE_A,
	STATE_B,
};
samma sak som

Kod: Markera allt

#define STATE_A 0
#define STATE_B 1
Det viktiga är att göra koden begriplig för andra (för då förstår man själv vad man gjorde när man tittar på koden tre månader senare, och det blir även mindre risk för buggar).

Nu när jag har sett labuppställningen (trevlig uppställning förresten! :tumupp: ) så skulle jag, istället för SENSOR_A och SENSOR_B kalla dessa typ PIN_ENC1_CHA ("encoder 1, channel A") och PIN_ENC1_CHB, och istället för "state" skulle jag använda typ "enc_state".

Kod: Markera allt

    enc_state = digitalRead(PIN_ENC1_CHA);
    enc_state |= digitalRead(PIN_ENC1_CHB) << 1;
Denna kod läser då in läget för kanal A i lägsta biten i enc_state. Läget för kanal B shiftas vänster en bit och läggs till ("OR:as") med läget för kanal A. Resultatet blir ett värde mellan 0 och 3. Nåt sånt här (inspirerat av denna sida):

Kod: Markera allt

enum state {
    ENC_STATE_LL,
    ENC_STATE_LH,
    ENC_STATE_HH,
    ENC_STATE_HL,
};

void checkState()
{
    enc_state = digitalRead(PIN_ENC1_CHA);
    enc_state |= digitalRead(PIN_ENC1_CHB) << 1;
    
    switch (old_state) {
    case ENC_STATE_LL:
        if (enc_state == ENC_STATE_LH)
            PulseCount++;
        else // enc_state == ENC_STATE_HL
            PulseCount--;
        break;

    case ENC_STATE_LH:
        if (enc_state == ENC_STATE_HH)
            PulseCount++;
        else // enc_state == ENC_STATE_LL
            PulseCount--;
        break;

    case ENC_STATE_HH:
        if (enc_state == ENC_STATE_HL)
            PulseCount++;
        else // enc_state == ENC_STATE_LH
            PulseCount--;
        break;

    case ENC_STATE_HL:
        if (enc_state == ENC_STATE_LL)
            PulseCount++;
        else // enc_state == ENC_STATE_HH
            PulseCount--;
        break;
 
    default:
        // Unknown state
    }
    
    old_state = enc_state;
}
Observera att mitt tidigare kodexempel, det som flyttade ut allt från loop(), inte kommer att fungera så bra: den läser bara av knapp- och stopp-sensorer när det kommer ett encoder-interrupt! Inte så bra. Lösningen är som sagt att lyfta ut läsning av knappar & sensorer från koden som uppdaterar lcdn och köra den koden varje loop - men bara anropa update_lcd() när det faktiskt finns något att uppdatera.

En annan förbättring är att även lägga knappar och sensorer på olika interrupt, så att kretsen reagerar direkt på ändringar i input. Som det är nu så kommer det att bli en fördröjning på i snitt halva delay()-värdet innan kretsen reagerar.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43148
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Vart i koden skriver jag fel?

Inlägg av sodjan »

När det gäller enum exemplen som arvidb pekade på så skull jag vilja peka på en sak till.

Antag att vi vill lägga till en STATE_C. I första fallet så blir det helt enkelt:

Kod: Markera allt

    enum state {
        STATE_A,
        STATE_B,
        STATE_C,
    };
I det andra fallet så är det väldigt lätt att man råkar skriva:

Kod: Markera allt

    #define STATE_A 0
    #define STATE_B 1
    #define STATE_C 1
Och det kommer att ställa till det rejält innan men hittar det... :-)

Fördelen (och poängen) med enum, är att det är helt ointressant vilket
numerisk värde som varje STATE_A, STATE_B o.s.v har, man använder
*alltid* de symboliska namnen, aldrig värdena som sådana.
Användarvisningsbild
arvidb
Inlägg: 4537
Blev medlem: 8 maj 2004, 12:56:24
Ort: Stockholm

Re: Vart i koden skriver jag fel?

Inlägg av arvidb »

... och där hittade sodjan en bugg i min kod, som slank in eftersom jag gör precis det som sodjan helt riktigt säger att man inte ska göra (jag använder värdena på ENC_STATE_xx när enc_state tilldelas med digitalRead()). ENC_STATE_HH och ENC_STATE_HL har ju blivit omkastade i enum-definitionen: ENC_STATE_HH ska ju ha värdet 3 (b11) och ENC_STATE_HL värdet 2 (b10). Bättre är nog att använda #defines i denna situation:

Kod: Markera allt

#define ENC_STATE_LL   0
#define ENC_STATE_LH   1
#define ENC_STATE_HL   2
#define ENC_STATE_HH   3
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43148
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Vart i koden skriver jag fel?

Inlägg av sodjan »

Ja, i de fall att det numeriska värdet på varje symbol *har* betydelse, så är #define bättre.
Ordningen på de olika #define raderna saknar ju också betydelse.

enum är som sagt smidigt för fall där *värdet* är ointressant.

Kod: Markera allt

    enum car_model {
       ford,
       volvo,
       saab,
    };
Hela tanken är att man bara ska kunna skilja dom åt.

(Ska även den sista symbolen i en enum ha ett komma!?)

Det kan bli problem med enum om det används för att läsa/jämföra
med datafält som kommer in t.ex. via någon kommunikation. Även där
kan #define vara bättre så att värdena kan anges explicit.
Användarvisningsbild
arvidb
Inlägg: 4537
Blev medlem: 8 maj 2004, 12:56:24
Ort: Stockholm

Re: Vart i koden skriver jag fel?

Inlägg av arvidb »

sodjan skrev:(Ska även den sista symbolen i en enum ha ett komma!?)
Det är valfritt i C99, inte tillåtet i C89. Jag brukar slänga med det eftersom det blir enklare när man vill lägga till ett fält till i enum:en (genom att kopiera det sista).
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43148
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Vart i koden skriver jag fel?

Inlägg av sodjan »

OK, det bara ser lite underligt ut... :-) Det underlättar i och för
sig något för automatiska kod generatorer och liknande...
Skriv svar