Sans griasst
Kurz zu mir:
Ich bin immer mal wieder mit dem Arduino in Berührung gekommen, habe aber bisher die Projekte immer wieder aufgegeben. Der Grund dafür war eigentlich immer das ich nicht wirklich programmieren kann und irgendwann vor "unlösbaren" Problemen stand. Naja oder ich habe halt immer etwas hoch gestapelt
.Das soll diesmal aber nicht passieren, weswegen ich mich nun an euch wende.
Von Anfang an:
Schlussendlich soll eine Spulenwickelmaschine entstehen welche via Potentiometer die Geschwindigkeit regeln, via Toggle-Switch die Drehrichtung steuern, via Hall-Sensor die Umdrehungen messen und diese auf einem Oled anzeigen soll. Das macht es prinzipiell auch mit folgendem Code:
#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
int in1 = 5; //Declaring where our module is wired
int in2 = 6;
int ConA = 9;// Don't forget this is a PWM DI/DO
int speed1;
int HallPinCounter = 0; // counter for the number of button presses
int HallPinState = 0; // current state of the button
int lastHallPinState = 0; // previous state of the button
const int HallPin = 7; // the pin that the hall sensor is attached to
const int SwitchPin_L = 11;
const int SwitchPin_R = 12;
void setup() {
// put your setup code here, to run once:
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(9, OUTPUT);
pinMode(SwitchPin_L, INPUT);
pinMode(SwitchPin_R, INPUT);
pinMode(HallPin, INPUT);
Serial.begin(9600);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
}
void TurnMotorAR() { //We create a function which control the direction and speed
//digitalWrite(SwitchPin_L, LOW);
digitalWrite(in1, LOW); //Switch between this HIGH and LOW to change direction
digitalWrite(in2, HIGH);
speed1 = analogRead(A0);
speed1 = speed1 * 0.2492668622; //We read thea analog value from the potentiometer calibrate it
analogWrite(ConA, speed1); // Then inject it to our motor
}
void TurnMotorAL() { //We create a function which control the direction and speed
//digitalWrite(SwitchPin_R, LOW);
digitalWrite(in1, HIGH); //Switch between this HIGH and LOW to change direction
digitalWrite(in2, LOW);
speed1 = analogRead(A0);
speed1 = speed1 * 0.2492668622; //We read thea analog value from the potentiometer calibrate it
analogWrite(ConA, speed1); // Then inject it to our motor
}
void TurnOFFA() {
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
analogWrite(ConA, 0);
}
void loop() {
// put your main code here, to run repeatedly:
HallPinState = digitalRead(HallPin);
// compare the HallPinState to its previous state
if (HallPinState != lastHallPinState) {
// if the state has changed, increment the counter
if (HallPinState == HIGH) {
// if the current state is HIGH then the button went from off to on:
HallPinCounter++;
Serial.print("Umdrehungen: ");
Serial.println(HallPinCounter);
}
// Delay a little bit to avoid bouncing
// delay(0);
}
// save the current state as the last state, for next time through the loop
lastHallPinState = HallPinState;
Serial.print("R");
Serial.println(digitalRead (SwitchPin_R));
Serial.print("L");
Serial.println(digitalRead (SwitchPin_L));
Serial.println(speed1);
if (digitalRead(SwitchPin_L) == HIGH) {
TurnMotorAR(); //one function that keeps looping you can add another one with different direction or stop
}
if (digitalRead(SwitchPin_R) == HIGH) {
TurnMotorAL(); //one function that keeps looping you can add another one with different direction or stop
}
display.clearDisplay();
display.setTextSize(3); // Draw 3X-scale text
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 20); // Start at top-left corner
display.println(HallPinCounter);
display.display();
}
Der Code ist wahrlich keine Augenweide, dies vor allem weil ich ähnliche Projekte gesucht habe und diese dann für meine Zwecke adaptiert. Der Sketch macht theoretisch was er soll. Alle Funktionen funktionieren, ABER ab einer gewissen Drehzahl traue ich dem Zähler nicht mehr. Er zählt trotz höherer Drehzahl langsamer. Also weiter recherchiert und auf das Gebiet "Interrupts" gestossen. Hört sich für mich so an als wäre das des Rätsels Lösung. Ich muss "nur" die Geschichte mit dem Hallsensor via Interrupt programmieren damit das zuverlässig unabhängig vom restlichen Code funktioniert.
Erfreulicher Weise habe ich den HallSensor zufällig an dem Interruptpin 7 meines Arduino Micro angelötet. In der Testphase auf dem Breadboard ist mir das Problem noch nicht aufgefallen.
Ich habe dann den Part den ich Interrupten will herausgeschält um etwas übersichtlicher Testen zu können. Ich habe allerlei ausprobiert, schaffe es aber nicht dass es funktioniert.
volatile int HallPinCounter = 0; // counter for the number of button presses
volatile int HallPinState = 0; // current state of the button
volatile int lastHallPinState = 0; // previous state of the button
volatile int HallPin = 7; // the pin that the hall sensor is attached to
void setup() {
// put your setup code here, to run once:
pinMode(HallPin, INPUT);
attachInterrupt(HallPin, Umdrehungen, CHANGE );
Serial.begin(9600);
}
void loop() {
Serial.println(HallPinCounter);
//Serial.println("HallPin"), Serial.print(digitalRead (HallPin));
}
void Umdrehungen () {
HallPinState = digitalRead(HallPin);
// compare the HallPinState to its previous state
if (HallPinState != lastHallPinState) { // if the state has changed, increment the counter
if (HallPinState == HIGH) {
HallPinCounter++; // if the current state is HIGH then the button went from off to on:
}
//delay(20);
}
lastHallPinState = HallPinState; // save the current state as the last state, for next time through the loop
}
Ich meine zu verstehen was ein Interrupt bräuchte (bspw. keine Delays) und ich meine auch zu verstehen was mein Sketch an der Stelle macht. Aber diese zwei Dinge zu kombinieren bin ich ausserstande
. Die Interrupt-Beispiele die ich gefunden habe sind immer "simpler" weswegen mir das adaptieren wahnsinnig schwer fällt.
Verwendete Hardware:
- Arduino Micro
- 12V Getriebemotor gesteuert mit L298n, Poti & Toggle
- 128*64 Oled Display
- DEBO SENS HALL A3141
Was muss ich tun um dieses Problem in den Griff zu bekommen?