Code:
/*
Interrupt Routine für Drehencoder von rafbuff, LCD vom SainSmart LCDShield, Motor Routine aus Tutorial
Das Dingens soll:
einen DC Motor rechts und links herum steuern, dabei die Geschwindigkeit per PWM
über den Drehencoder erhöhen/verringern, die Encoder-Werte auf dem LCD ausgeben.
Am LCD Shield sind einige Taster angebracht, die über eine Widerstandsleiter an
einem Analogeingang dekodiert werden. Stammt aus dem Example zum LCD-Shield. Das ist pfiffig, denn die digitalen Inputs
würden bei normaler Beschaltung jedes Tasters an einem digitalen In nicht
ausreichen...
*/
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
char LCDChar[2]="";
// Drehencoder-Deklaration: A & B, Gnd in der Mitte, Achtung 100nF und 10k als Debouncer-Glied...
int motor1_A=5;
int motor1_B=4;
int motor1_PWM=13;
enum PinAssignments {
encoderPinA = 2, // rigth , Speed up
encoderPinB = 3, // left , Speed down
clearButton = ? // Stop-Button, Taster am Drehencoder
LinksButton = ? // Laufrichtung Links Taster
RechtsButton ? // Laufrichtung Rechts Taster
};
volatile unsigned int encoderPos = 0; // a counter for the dial
unsigned int lastReportedPos = 1; // change management
static boolean rotating=false; // debounce management
// interrupt service routine vars
boolean A_set = false;
boolean B_set = false;
//ab hier die Tasterabfrage:
********************************************************/
// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
// define some values used by the panel and buttons
int backLight = 10; // LCD Panel Backlight LED connected to digital pin 10
int lightLevel = 255; // Initialise light full on
int lcd_key = 0;
int adc_key_in = 0;
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
// read the buttons
int read_LCD_buttons()
{
adc_key_in = analogRead(0); // read the value from the resistor-ladder
// my [Mark Bramwell's] buttons when read are centered at these valies: 0, 144, 329, 504, 741
// we add approx 50 to those values and check to see if we are close
if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 195) return btnUP;
if (adc_key_in < 380) return btnDOWN;
if (adc_key_in < 555) return btnLEFT;
if (adc_key_in < 790) return btnSELECT;
return btnNONE; // when all others fail, return this...
}
//********************************************************
void setup() {
//Motor Pins deklarieren:
pinMode(motor1_A,OUTPUT);
pinMode(motor1_B,OUTPUT);
//Encoder Pins decl.
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
//LCD starten
lcd.begin(16, 2); // 16x2 LCD panel
lcd.setCursor(0,0);
lcd.print("LCD KeyPadShield");
lcd.setCursor(0,1);
lcd.print("<Character Set>");
delay(2000);
// Pullups setzen
digitalWrite(encoderPinA, HIGH);
digitalWrite(encoderPinB, HIGH);
// Encoder pin on interrupt 0 (pin 2)
attachInterrupt(0, doEncoderA, CHANGE);
// Encoder pin on interrupt 1 (pin 3)
attachInterrupt(1, doEncoderB, CHANGE);
}
//********************************************************
// main loop, work is done by interrupt service routines; set motor
void loop() {
lcd.clear();
for(int i=0; i<=255; i++){
lcd.setCursor(0,0);
lcd.print("Drehzahl= ");
sprintf(LCDChar, "0x%02X", i);
lcd.print(LCDChar);
lcd.setCursor(5,1);
lcd.print(encoderPos, DEC);
delay(500);
//********************************************************
//ab hier geht's um den Drehencoder:
rotating = true; // reset the debouncer
if (lastReportedPos != encoderPos) {
lcd.print("Geschwind.: ");
lcd.print( encoderPos, DEC);
lastReportedPos = encoderPos;
}
if (digitalRead(clearButton) == LOW ) {
encoderPos = 0;
}
}
// Interrupt on A changing state
void doEncoderA(){
// debounce
if ( rotating ) delay (1); // wait a little - 1 ms - until the bouncing is
done
// Test transition, did things really change?
if( digitalRead(encoderPinA) != A_set ) { // debounce once more
A_set = !A_set;
// adjust counter + if A leads B
if ( A_set && !B_set )
encoderPos += 10;
rotating = false; // no more debouncing until loop() hits again
}
}
// Interrupt on B changing state, same as A above
void doEncoderB(){
if ( rotating ) delay (1);
if( digitalRead(encoderPinB) != B_set ) {
B_set = !B_set;
// adjust counter - 1 if B leads A
if( B_set && !A_set )
encoderPos -= 10;
rotating = false; // no more debouncing until loop() hits again
}
// ab hier - die Motor Ansteuerung
//********************************************************
// Rechts drehen
digitalWrite(motor1_A,HIGH); // A = HIGH and B = LOW means the motor will turn right
digitalWrite(motor1_B,LOW);
digitalRead(motor1_Speed, encoderPos); // speed is taken over from encoder
Position
}
//Links drehen
digitalWrite(motor1_A,LOW); // A = LOW and B = HIGH means the motor will turn left
digitalWrite(motor1_B,HIGH);
digitalRead(motor1_Speed, encoderPos); // speed is taken over from encoder
Position
}
//Ab hier die Tastenabfrage und Ausgabe auf LCD:
{
switch (lcd_key) // depending on which button was pushed, we perform an action
{
case btnRIGHT:
{
lcd.print("LED On ");
lightLevel = 255;
break;
}
case btnLEFT:
{
lcd.print("LED Off ");
lightLevel = 1;
break;
}
case btnUP:
{
lcd.print("LED Fade Up ");
if (lightLevel < 255) lightLevel += 1;
break;
}
case btnDOWN:
{
lcd.print("LED Fade Down ");
if (lightLevel > 1) lightLevel -= 1;
break;
}
case btnSELECT:
{
lcd.print("Select ");
break;
}
case btnNONE:
{
lcd.print(" ");
break;
}
}
}
}
Lesezeichen