Vraag


Acties:
  • 0 Henk 'm!

  • stefan787
  • Registratie: Maart 2013
  • Laatst online: 26-09 08:37
Beste Tweakers!

op het moment ben ik bezig met een hobby project en probeer ik een eigen module te maken die mijn frequentieregelaar kan aansturen. Op deze module zit een lcd scherm en een encoder.
Met behulp van de encoder wil ik graag door een menu op het lcd schermpje kunnen scrollen.

Alleen het lukt mij niet om de encoder zo te programmeren dat hij netjes op en af telt. de uitkomst is niet stabiel en springt veel op en neer.

Op het internet zijn natuurlijk veel voorbeelden te vinden van een encoder alleen bij dit project wil ik graag dat als een getal boven een waarde komt dat ie dan weer naar nul gaat. en andersom van minimale naar maximale waarde. zodat ik als het waarde door. Ik hoop dat de flowchart hieronder duidelijkheid schept.

https://stefan787.stackstorage.com/s/PcfW8cZo5f5gB1U

uiteindelijk wil ik van de code die ik heb een functie maken zodat ik de
MaxValue, MinValue en StepSize
per pagina op het display kan aan passen.

dit is het overzicht van de opbouw van het uiteidelijke display:

https://stefan787.stackstorage.com/s/XMlnuzcbnCIczG7

Als ik dan bij Set RPM CW sta en ik klik dan op de schakelaar van de encoder dat ik dan vervolgens aan de encoder kan draaien en een toerental kan instellen.

Dan moeten de volgende waarde:
MaxValue, MinValue en StepSize
3000, 250 en 50 worden.

maar hiervoor heb ik eerste een goed werkende encoder nodig.

dit is de code die ik nu heb staan:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/*
 Name:      Main_V0.ino
 Created:   10/1/2018 5:12:10 PM
 Author:    Stefan de Kraker
 Flow chart: https://www.draw.io/#LFlow_Menu_frequentieregelaar.xml
*/


// encoder setup
const int OutputA = 2;
const int OutputB = 4;
const int OutputSW = 3;
int EncoderVal = 0;

// setup RPM
int Waarde = 0;
static int MaxValue = 3000;
static int MinValue = 250;


// setup Menu
int MenuLevel = 0;

void setup()
{
    pinMode(7, OUTPUT);
    pinMode(OutputA, INPUT);
    pinMode(OutputB, INPUT);
    pinMode(OutputSW, INPUT);
    digitalWrite(OutputSW, HIGH);
    Serial.begin(9600);
}


void loop() {
    int change = getEncoderTurn();
    EncoderVal = EncoderVal + change;
    overflow(1,6,1);
};

int getEncoderTurn() {
    static int oldA = HIGH;
    static int oldB = HIGH;
    int result = 0;
    int newA = digitalRead(OutputA);
    int newB = digitalRead(OutputB);
    if (newA != oldA || newB != oldB) {
        if (oldA == HIGH && newA == LOW)
        {
            result = (oldB * 2 - 1);
            //Serial.println("EncoderVal: ");
            //Serial.println(EncoderVal);
            Serial.println(Waarde);
        }
    }
    oldA = newA;
    oldB = newB;
        return result;
}
void overflow(int StepSize, int MaxValue, int MinValue) {
    if (EncoderVal >= 1) {
        Waarde = Waarde + StepSize;
        EncoderVal = 0;
    }
    if (EncoderVal == -1) {
        Waarde = Waarde - StepSize;
        EncoderVal = 0;
    }
    if (Waarde > MaxValue) {
        Waarde = MinValue;
    }
    if (Waarde < MinValue) {
        Waarde = MaxValue;
    }
}

Ik hoop dat iemand er naar kan kijken en mij kan helpen, ik ben hier namelijk al eigenlijk al te lang mee bezig wordt er nu een beetje :( van.

Alvast bedankt!! :)

[ Voor 30% gewijzigd door stefan787 op 02-10-2018 08:51 ]

Beste antwoord (via stefan787 op 02-10-2018 20:16)


  • TommyboyNL
  • Registratie: Januari 2006
  • Niet online
Daar staat dit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package nl.han.dea.fedor;

import nl.han.dea.fedor.adapters.KoenenDictionaryAdapter;
import nl.oose.dea.koenenkramers.KoenenDictionary;

public class DictionaryFactory {

    public static Dictionary create(String type) {
        if ("Koenen".equals(type)) {
            return new KoenenDictionaryAdapter(new KoenenDictionary());
//        } else if ("Kramers".equals(name)) {
            //           return new KramersDictionaryAdapter();
        }
        return null;
    }

}

Ik denk niet dat dit jouw code is...

Edit:

In het verleden heb ik deze library gebruikt, met dezelfde functionaliteit als jij; tussen 0 en x met rollover. Ik zal eens kijken of ik een snippet uit mijn code kan halen.

Edit2: Nee, te veel gedoe om mijn routines uit de rest van de code te slopen. Lelijke pseudocode uitgaande van bovenstaande library:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
init{
value = 1000; // Varieert van 100 tot 2000
rotary = read_rotary();
rotary_old = rotaty;
}

main{
label A;

rotary = read_rotary();
if (rotary == rotary_old) goto A;
value += (rotary-rotary_old);
if (value > 2000) vaule -= 1901; // Overflow
if (value < 100) value += += 1901; // Underflow
rotary_old = rotary;
}


Denkoefening voor jou: waarom niet "if (value == 2001) vaule -= 1901;"

[ Voor 35% gewijzigd door TommyboyNL op 02-10-2018 22:27 ]

Alle reacties


Acties:
  • Beste antwoord
  • +1 Henk 'm!

  • TommyboyNL
  • Registratie: Januari 2006
  • Niet online
Daar staat dit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package nl.han.dea.fedor;

import nl.han.dea.fedor.adapters.KoenenDictionaryAdapter;
import nl.oose.dea.koenenkramers.KoenenDictionary;

public class DictionaryFactory {

    public static Dictionary create(String type) {
        if ("Koenen".equals(type)) {
            return new KoenenDictionaryAdapter(new KoenenDictionary());
//        } else if ("Kramers".equals(name)) {
            //           return new KramersDictionaryAdapter();
        }
        return null;
    }

}

Ik denk niet dat dit jouw code is...

Edit:

In het verleden heb ik deze library gebruikt, met dezelfde functionaliteit als jij; tussen 0 en x met rollover. Ik zal eens kijken of ik een snippet uit mijn code kan halen.

Edit2: Nee, te veel gedoe om mijn routines uit de rest van de code te slopen. Lelijke pseudocode uitgaande van bovenstaande library:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
init{
value = 1000; // Varieert van 100 tot 2000
rotary = read_rotary();
rotary_old = rotaty;
}

main{
label A;

rotary = read_rotary();
if (rotary == rotary_old) goto A;
value += (rotary-rotary_old);
if (value > 2000) vaule -= 1901; // Overflow
if (value < 100) value += += 1901; // Underflow
rotary_old = rotary;
}


Denkoefening voor jou: waarom niet "if (value == 2001) vaule -= 1901;"

[ Voor 35% gewijzigd door TommyboyNL op 02-10-2018 22:27 ]


Acties:
  • 0 Henk 'm!

  • stefan787
  • Registratie: Maart 2013
  • Laatst online: 26-09 08:37
Bedankt voor je voorbeeld, ik ga eens kijken of ik dit kan toepassen!
Alleen nu zijn de stappen die value neemt nog steeds 1, hierover zou ik graag ook controle willen hebben dus dat de value met bijvoorbeeld 20 oploopt.

Acties:
  • +1 Henk 'm!

  • spork
  • Registratie: Maart 2009
  • Laatst online: 30-09 14:02
Dat is een kwestie van "value += (rotary-rotary_old);" vervangen door "value += 20*(rotary-rotary_old);"
Of elke andere willekeurige waarde natuurlijk.

Acties:
  • +1 Henk 'm!

  • stefan787
  • Registratie: Maart 2013
  • Laatst online: 26-09 08:37
Ik ben nu een aantal uurtjes bezig geweest met jullie tips.

En met succes. @TommyboyNL de libary heb ik toegepast en dit werkt echt een stuk beter.
Kan nu mooi door scrollen door me menu en met rollover. Daarnaast staat het nu ook in een functie die ik elke keer aan aan roepen met andere variabelen.

het display heb ik nu nog niet even gebruikt, tijdelijk even een rij ledjes, en ik kan mooi elk led één voor één aan en uit zetten. en als ik bij het eerste ledje sta en ik klik op de knop van de encoder dan kan ik een andere led dimmen. `

https://stefan787.stackstorage.com/s/0bFSnhV99M0KgVi

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
 Name:      Main_V0.ino
 Created:   10/1/2018 5:12:10 PM
 Author:    Stefan de Kraker
 Flow chart: https://www.draw.io/#LFlow_Menu_frequentieregelaar.xml
*/

// Setup Encoder
#include <Encoder.h>
Encoder Knop(3, 2);
const int OutputSW = 4;
int OldDraaiKnop = -999;
int Waarde;

// Setup LCD en Menu 
int MenuLevel = 0;
bool InMenu = false;
bool A; // EnterMenu
bool B; // ExitMenu

// Ledjes, dit gaat straks weer weg
int led1 = 12;
int led2 = 11;
int led3 = 10;
int led4 = 9;
int led5 = 7;


// Setup voor toerental en stapgroote en max toerental
int RPMCW;
int RPMCCW;
const int MAXPRM = 3000;
const int StepSizeRPM = 50;
float OutputRPMCW;

void setup() {
    //Serial.begin(9600);
    pinMode(led1, OUTPUT);
    pinMode(led2, OUTPUT);
    pinMode(led3, OUTPUT);
    pinMode(led4, OUTPUT);
    pinMode(led5, OUTPUT);
    // Setup Pullup voor EncoderSW
    pinMode(OutputSW, INPUT_PULLUP);
}

void loop()
{
    if (InMenu == false) {
        MenuLevel = ReadEncoderData(1, 4, 0);
        led();
        EnterMenu();
        //Serial.print(MenuLevel);
    }
    if (InMenu == true) {
        if (MenuLevel == 0) { // Set RPM CW
            ExitMenu();
            RPMCW = ReadEncoderData(StepSizeRPM, MAXPRM, 0);
            ConvertRPM();
            
        }
        if (MenuLevel == 1) { // Set RPM CCW
            ExitMenu();
            RPMCCW = ReadEncoderData(StepSizeRPM, MAXPRM, 0);
            //Serial.print(RPMCCW);
        }
    }
}

int ReadEncoderData(int StepSize, int Maxavalue, int Minvalue) {
    long DraaiKnop;
    DraaiKnop = Knop.read();
    if (DraaiKnop != OldDraaiKnop) {
        OldDraaiKnop = DraaiKnop;
    }
    if (DraaiKnop == 4) {
        Waarde = Waarde + StepSize;
        Knop.write(0);
    }
    if (DraaiKnop == -4) {
        Waarde = Waarde - StepSize;
        Knop.write(0);
    }
    if (Waarde > Maxavalue) {
        Waarde = Minvalue;
    }
    if (Waarde < Minvalue) {
        Waarde = Maxavalue;
    }
    return Waarde;
}

void EnterMenu() {
    if (digitalRead(OutputSW) == LOW) {
        A = true;
    }
    if (digitalRead(OutputSW) == HIGH && A == true) {
        InMenu = true;
        A = false;
    }
}

void ExitMenu() {
    if (digitalRead(OutputSW) == LOW) {
        B = true;
    }
    if (digitalRead(OutputSW) == HIGH && B == true) {
        InMenu = false;
        B = false;
    }
}

void ConvertRPM() {
    OutputRPMCW =  (float) RPMCW / 11.7;
    Serial.println(OutputRPMCW);
    analogWrite(led4, OutputRPMCW);
}

void led() {
    if (MenuLevel == 0) {
        digitalWrite(led1, HIGH);
    }
    else {
        digitalWrite(led1, LOW);
    }
    if (MenuLevel == 1) {
        digitalWrite(led2, HIGH);
    }
    else {
        digitalWrite(led2, LOW);
    }
    if (MenuLevel == 2) {
        digitalWrite(led3, HIGH);
    }
    else {
        digitalWrite(led3, LOW);
    }
    if (MenuLevel == 3) {
        digitalWrite(led4, HIGH);
    }
    else {
        digitalWrite(led4, LOW);
    }
    if (MenuLevel == 4) {
        digitalWrite(led5, HIGH);
    }
    else {
        digitalWrite(led5, LOW);
    }
}

Acties:
  • 0 Henk 'm!

  • TommyboyNL
  • Registratie: Januari 2006
  • Niet online
@stefan787 Mooi dat het je gelukt is, en ook netjes dat je je code post. Veel succes met de rest van je project.

Acties:
  • +2 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 27-09 13:03
Voor de goede orde, een dergelijke encoder wordt normaal gesproken (als de hardware geen peripheral heeft die encoders ondersteunt) op basis van edge-interrupts ingelezen. Het idee is dan om op de flanken van je puls/pulsen te kijken wat de status van de andere ingang is en op basis daar van op of af te tellen.

NB
Deze code
C++:
1
2
3
4
5
    long DraaiKnop;
    DraaiKnop = Knop.read();
    if (DraaiKnop != OldDraaiKnop) {
        OldDraaiKnop = DraaiKnop;
    }

kun je vereenvoudigen naar:
C++:
1
2
    long DraaiKnop = Knop.read();
    OldDraaiKnop = DraaiKnop;

op basis waarvan je kunt concluderen dat OldDraaiKnop overbodig is.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.

Pagina: 1