ich habe mir ein Script geschrieben, welches ein Tachometer für's Fahrrad mit dem ATtiny85 werden soll. Aber leider funktioniert es nur auf den Atmega 328 Boards (Uno, Nano). Was muss ich für den Tiny anders machen? Ich habe den Bootloader auf 8 MHz eingestellt und nutze den ATtinyCore von Spencer Konde. Millis() ist enabled und funktioniert. Als Sensor nutze ich ein Reed-Kontakt-Modul und dort den digitalen Pin (geht an Pin 3 beim Uno und beim ATtiny85).
Hier das Script für den Uno:
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C // See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const int reedPin = 3; // Digital pin reed module
int lastReedState = 0; // Last reed state
unsigned long lastTime = 0; // Last time
int revolutions = 0; // Revolutions
float distance = 0.0; // Distance in km
float speed = 0.0; // Speed in km/h
const float circumference = 0.223; // 28" in meter (223 cm = 2.23 m)
void setup() {
pinMode(reedPin, INPUT);
Serial.begin(9600);
display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
display.clearDisplay();
display.display();
}
void loop() {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0, 10);
int currentReedState = digitalRead(reedPin);
if (currentReedState != lastReedState) {
if (currentReedState == HIGH) {
revolutions++;
distance = revolutions * circumference;
speed = (distance / (millis() - lastTime) * 3600.0);
lastTime = millis();
Serial.print("Revolutions: ");
Serial.println(revolutions);
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" km");
Serial.print("Speed: ");
Serial.print(speed);
Serial.println(" km/h");
display.print(distance);
display.println(" km");
display.print(speed);
display.println(" km/h");
display.display();
}
}
lastReedState = currentReedState;
}
Auf dem Tiny nutze ich die <Tiny4kOLED.h>, welche prima funktioniert. Aber auf dem ATtiny bekomme ich keinen vernünftigen Output auf dem Display. Da erscheinen zwar so circa alle 2 s Werte für Distance und Speed, diese verändern sich aber selbständig ohne Input vom Reed Kontakt.
Hier der Code für den Tiny:
// Tachometer Fahrrad
#include <Tiny4kOLED.h>
const int reedPin = 3; // Digital pin reed module
int lastReedState = 0; // Last reed state
unsigned long lastTime = 0; // Last time
int revolutions = 0; // Revolutions
float distance = 0.0; // Distance in km
float speed = 0.0; // Speed in km/h
const float circumference = 0.223; // 28" in meter (223 cm = 2.23 m)
void setup() {
pinMode(reedPin, INPUT);
oled.begin(128, 64, sizeof(tiny4koled_init_defaults), tiny4koled_init_defaults);
oled.enableChargePump(); // The default is off, but most boards need this.
oled.setRotation(1); // The default orientation is not the most commonly used.
oled.clear();
oled.setFontX2(FONT6X8P);
oled.setCursor(0, 0);
oled.on();
}
void loop() {
oled.clear();
int currentReedState = digitalRead(reedPin);
if (currentReedState != lastReedState) {
if (currentReedState == HIGH) {
revolutions++;
distance = revolutions * circumference;
speed = (distance / (millis() - lastTime) * 3600.0);
lastTime = millis();
oled.print(distance);
oled.println(" km");
oled.print(speed);
oled.println(" km/h");
}
}
lastReedState = currentReedState;
}
Im englischen Teil des Forum müssen die Beiträge und Diskussionen in englischer Sprache verfasst werden. Deswegen wurde diese Diskussion in den deutschen Teil des Forums verschoben.
(mit Google translate)
Ich schlage vor, dass Sie stattdessen INPUT_PULLUP verwenden und den Reed-Kontakt mit GND statt mit VCC verbinden. Dadurch wird ein schwebender Eingangspin verhindert, da dieser bei offenem Reed-Kontakt nicht stabil ist.
Es sei denn, Sie haben am Reedschalter einen Pulldown-Widerstand gegen GND verwendet.
// Tachometer Fahrrad
#include <Tiny4kOLED.h>
const int reedPin = 3; // Digital pin reed module
int lastReedState = 0; // Last reed state
unsigned long lastTime = 0; // Last time
int revolutions = 0; // Revolutions
float distance = 0.0; // Distance in km
float speed = 0.0; // Speed in km/h
const float circumference = 0.223; // 28" in meter (223 cm = 2.23 m)
void setup() {
pinMode(reedPin, INPUT_PULLUP);
oled.begin(128, 64, sizeof(tiny4koled_init_defaults), tiny4koled_init_defaults);
oled.enableChargePump(); // The default is off, but most boards need this.
oled.setRotation(1); // The default orientation is not the most commonly used.
oled.clear();
oled.setFontX2(FONT6X8P);
oled.setCursor(0, 0);
oled.on();
}
void loop() {
oled.clear();
int currentReedState = digitalRead(reedPin);
if (currentReedState != lastReedState) {
if (currentReedState == LOW) {
revolutions++;
distance = revolutions * circumference;
speed = (distance / (millis() - lastTime) * 3600.0);
lastTime = millis();
oled.print(distance);
oled.println(" km");
oled.print(speed);
oled.println(" km/h");
}
}
lastReedState = currentReedState;
}
Ich wurde als erstes oled.clear(); aus der Loop rauswerfen, normaler weise löscht das bei jedem loop durchlauf das Display.
Was aber sein kann das die anzeige der Werte werden zugeschmiert, könne die Tiny4kOLED.h nicht, was mir noch fehlt ist
Man macht ein kleines Menü in der LOOP und ruft ja nach Auswahl den /die Passende Unterroutine auf.
Die Art der Auswahl ist egal. Bei mir meist Tasten/Tastatur und Display oder seit neusten Touchscreen.
Bei selbst startenden Aufgaben, wird der 1 Tastendruck simuliert.
Der Vorteil ist:
1.) Schneller Austausch von Sub-Routinen. Da die meisten Variablen nur in der Sub-Routine gültig sind, muß man nicht auf Doppeldeklartionen achten.
2.) Schnelles und flexibles Arbeiten. Da viele Grundeinstellungen gleich sind.
Das ganze nennt man Modularen Programmieren.
Eine leichte Abweichung davon machen viele Firmen in den sie den Kunden das Grundgerüst verkaufen, und gewisse Programmmodule Extra.
so, habe jetzt etwas herumexperimentiert und folgende Ergebnisse:
Der Code war im großen und ganzen ok, aber der ATtiny produzierte teilweise ein seltsames Verhalten. Ein INPUT_PULLUP scheint beim Tiny nicht zu funktionieren, deshalb muss ein Pullup oder Pulldown Widerstand an den Eingang, danke für den Tipp. Die OLED Library ist ok und erkennt I2C automatisch.
Ich habe jetzt folgenden Code:
// Tachometer Fahrrad
#include <Tiny4kOLED.h>
const int hallPin = 3; // Digital pin hall sensor
int lastHallState = 0; // Last hall state
unsigned long lastTime = 0; // Last time
int revolutions = 0; // Revolutions
float distance = 0.0; // Total distance
float totalTime = 0.0; // Total time
const float revDistance = 0.00223; // Distance per revolution; 28" in meter (223 cm = 0.00223 km)
float revSpeed = 0.0; // Speed in km/h
void setup() {
pinMode(hallPin, INPUT);
oled.begin(128, 64, sizeof(tiny4koled_init_defaults), tiny4koled_init_defaults); // Init display
oled.enableChargePump(); // The default is off, but most boards need this.
oled.setRotation(1); // The default orientation is not the most commonly used.
oled.clear(); // Clear display
oled.setFontX2(FONT6X8P); // Set fonts
oled.setCursor(0, 0); // Set cursor
oled.on();
}
void loop() {
int currentHallState = digitalRead(hallPin);
if (currentHallState != lastHallState) {
if (currentHallState == LOW) {
revolutions++;
distance = revolutions * revDistance;
float revTime = (millis() - lastTime) / 1000.0 / 3600.0;
totalTime = totalTime + revTime;
revSpeed = revDistance / revTime;
oled.clear();
oled.println(revolutions);
oled.print(distance, 1);
oled.println(" km");
oled.print(totalTime);
oled.println(" h");
oled.print(revSpeed, 1);
oled.println(" km/h");
lastTime = millis();
}
}
lastHallState = currentHallState;
}
Solange ich einen Button mit 10k Pullup an Pin 3 hänge, funktioniert alles tadellos (sofern ich mit meinen Berechnungen für Zeit und Geschwindigkeit richtig liege :)).
Aber sobald ich einen Hall Sensor anschließe (zieht den Pin auch gegen 10k nach Ground), macht der ATtiny wieder seltsame Dinge. Er zählt ohne externen Trigger auf einen revolution-Wert zwischen 11 und 14 hoch und hängt sich dann auf. D.h. er reagiert gar nicht mehr auf einen externen Trigger
Was passiert hier?
Nicht das es am Hall Sensor selber liegt, es gibt ja 3 Sorten, Analoge, Digitale, Digitale mit selbst Haltung, die letzten brauchen ja 2 Magnetfelder zum schalten ein mall N und S.
Mit den Anlogen bin mall selber in die Falle gelaufen, war aber kein ATtiny nur ein Nano R3.
Die Digitale brauchen ein Pull Up.