Liebe Forummitglieder, ich habe ein eigenartiges Phänomen:
bei einigen Textausgaben auf dem OLED 128 x 64 SSD1306 habe ich am unteren Rand immer so komische sichtbare Pixel. Immer dann, wenn ich nicht nur Text sondern Werte ausgebe.
Damit ihr euch nicht durch den elend langen sketch durchackern müßt (der im Wesentlichen von my_xy_projekt stammt und unter "Simpler Dosierspender" hier im Forum zu finden ist), habe ich euch die dazugehörigen sketch-Schnippsel zu den Fotos angehängt.
Hat da jemand eine Erklärung und eine Lösung dafür?
Ich habe schon display.println() als letzte Zeile hinzugefügt - ändert nix.
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.
Das Verschmutzt scheint mir eine interpretation der Zahl als Bit-Pixel also grafisch.
Hast Du irgendwo (ungewollt) eine Umschaltung von Text nach Grafikmodus?
Hi Uwe,
nicht das ich wüßte. Weiß gar nicht wie das geht, bin newbe
Es hängt auch nicht mit ev. Umlauten zusammen. Bloß wenn Werte ausgelesen werden, dann tauchen sie auf.
Ich weiß auch nicht ob's geht es sieht nur so aus.
Könnte mir vorstellen daß Du ein Ram-Problem hast wo dieser Bereich des "Bildschirmspeichers" überschrieben wird.
Ohne Sketch könnenwir Dir nichts sagen. Ich glaube Du mußt uns den gesamten Sketch geben. Bitte links auf die verwendeten Bibliotheken.
Welchen Arduino verwendest Du? Hast Du es mit einem Arduino Mega schon versucht?
ok. Ich verwende einen Arduino Nano.
Eine Bitte: lacht nicht über den sketch, man könnte den sicher kompakter und professioneller machen, aber ich bin am Lernen und da beginne ich simple by simple
Also hier der Sketch:
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Servo.h>
#include <AccelStepper.h>
//Taster:
const byte SaugT =12; //Taste auf D12: Ansaugen ohne Zeitnehmung
const byte DosierT = 11; // Taste auf D11: Vorgabezeit programmieren
const byte StopT = 10; // Set / Stopp Taste = Abbruch
const byte FuellT = 9; // Taste: Fülle bis Vorgabewert
const byte DrehT = 5; // zum Drehen des Motors zur nächsten Flasche
const byte FCS = 6; // checkt, ob Flasche vorhanden
const byte Relais = 4; // Relais
const unsigned long bounceTime = 200; //Entprellzeit
unsigned long FuellTime;
unsigned long vorgabezeit; //gemerkte Zeit als Vorgabe für autom. Befüllen
unsigned long duration; // Variable für die Dauer des Tastendrucks
unsigned long fuellStartTime = 0; // millis-Wert beim ersten Drücken der Taste
#define OLED_RESET 0
//#define SSD1306_128_64
Adafruit_SSD1306 display(128, 64); // Breite, Höhe
//Adafruit_SSD1306 display(OLED_RESET);
//Servomotor
Servo myservo;
int pos = 0;
//Steppermotor 17HS19
const int dirPin = 2; // Richtung StepperMotor
const int stepPin = 3; // Ansteuerung StepperMotor
#define motorInterfaceType 1
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin); // Create a new instance of the AccelStepper class:
void AccelStepper::disableOutputs (); //Spulen stromlos machen um Strom zu sparen
void setup() {
//Eingänge:
pinMode (SaugT, INPUT_PULLUP); // Pullup-Widerstand aktivieren
pinMode (DosierT, INPUT_PULLUP); // Pullup-Widerstand aktivieren
pinMode (FuellT, INPUT_PULLUP); // Pullup-Widerstand aktivieren
pinMode (StopT, INPUT_PULLUP); // Pullup-Widerstand aktivieren
pinMode (DrehT, INPUT_PULLUP); //dreht Motor zur nächsten Flasche
pinMode (FCS, INPUT_PULLUP); //checkt ob Flasche vorhanden
//Ausgänge:
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(Relais, OUTPUT);
digitalWrite(Relais, LOW); //Relais standardmäßig abgefallen
myservo.attach(7); //Servomotor auf PIN 7
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
myservo.write(0);
//StepperMotor:
stepper.setMaxSpeed(1000); //Set maximum speed in steps per second
stepper.setAcceleration(400);
stepper.setCurrentPosition(0);
//Serieller Monitor
Serial.begin(115200);
Serial.println(F("Start..."));
//OLED Display Anzeige
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
//display.display();
display.clearDisplay();
display.setCursor(0,17);
display.setTextSize(2);
display.setTextColor(WHITE);
display.println("R E A D Y");
display.display();
}
void loop()
{
if (!ansaugen())
if (!programmieren())
ablauf();
drehen();
}
//=====================================================================
bool ansaugen()
{
static uint32_t lastmillis = 0;
static bool ausloeser = false;
if ((!digitalRead(FCS)) && (!digitalRead(SaugT))) // FCS UND SaugTaste gedrueckt? ...
{
ausloeser = true;
if (!digitalRead(Relais)) // ... und Relais ist aus? ...
{
lastmillis = millis();
myservo.write(70);
delay (500);
digitalWrite (Relais , HIGH); // Relais an
Serial.println(F("Ansaugen gestartet..."));
Serial.println("");
display.clearDisplay();
display.setCursor(0,9);
display.println("ANSAUGEN:");
display.print(" START");
display.display();
}
}
else if (ausloeser) // ausloeser gesetz?
if (millis() - lastmillis > bounceTime) // Taste losgelassen und deboncetime
{
digitalWrite (Relais , LOW); // mache Relais wieder aus
delay(500);
myservo.write(0);
Serial.println("Ansaugen gestoppt");
Serial.println("");
display.clearDisplay();
display.setCursor(0,9);
display.println("ANSAUGEN:");
display.println(" STOPP");
display.display();
ausloeser = false;
}
return ausloeser;
}
//======================================================================
bool programmieren()
{
enum {warten, dosieren, uebernahme};
static uint32_t zeitsammler = 0;
static uint32_t startTime = 0;
static uint32_t lastmillis = 0;
static byte status = warten;
switch (status)
{
case warten:
if ((!digitalRead(FCS)) && (!digitalRead(DosierT))) // Programmiertaste ausgelöst
{
status = dosieren;
myservo.write(70);
delay (500);
digitalWrite (Relais , HIGH); // zieht Relais an
Serial.println("Dosieren gestartet...");
startTime = millis(); // Zeit merken
lastmillis = millis();
display.clearDisplay();
display.setCursor(0,9);
display.println("DOSIEREN:");
display.print(" START");
display.display();
}
break;
case dosieren:
if (millis() - lastmillis > bounceTime)
{
if (digitalRead(DosierT))
{
digitalWrite (Relais , LOW); // mache Relais wieder aus
delay(500);
myservo.write(0);
zeitsammler += (millis() - startTime); // berechne Zeit
Serial.print(F("Dauer = "));
Serial.print((float)zeitsammler / 1000);
Serial.println(F(" Sek"));
Serial.println();
status = uebernahme;
lastmillis = millis();
display.clearDisplay();
display.setCursor(0,9);
display.println("DAUER:");
display.print((float)zeitsammler /1000);
display.println(" Sek");
display.display();
}
}
break;
case uebernahme:
if (millis() - lastmillis > bounceTime)
{
if (!digitalRead(StopT))
{
duration = zeitsammler;
Serial.print(F("Vorgabezeit = "));
Serial.print((float)duration/1000);
Serial.print(F(" Sek"));
Serial.println(" übernommen");
Serial.println();
display.clearDisplay();
display.setCursor(0,5);
display.println("Vorgabe:");
display.print((float)zeitsammler/1000);
display.println(" Sek");
display.print("\201bernommen");
display.display();
zeitsammler = 0;
status = warten;
}
if (!digitalRead(DosierT))
{
Serial.println(F(" zähle hinzu"));
Serial.println();
display.clearDisplay();
display.setCursor(0,15);
display.println("z\204hle");
display.print("hinzu:");
display.display();
status = warten;
}
}
break;
}
return status;
}
//======================================================================
void ablauf()
{
static uint32_t startTime = 0;
stepper.setCurrentPosition(0);
if ((!digitalRead(FCS)) && (!digitalRead(FuellT)))
{
if (!digitalRead(Relais))
{
Serial.println(F("Starte Relais...."));
display.clearDisplay();
display.setCursor(0,9);
display.println("BEF\201LLEN:");
display.print(" START");
display.display();
startTime = millis();
myservo.write(70);
delay(500);
digitalWrite (Relais , HIGH); // zieht Relais an
}
}
if (!digitalRead(StopT) && digitalRead(Relais))
{
digitalWrite(Relais, LOW);
Serial.print("GESTOPPT = ");
display.clearDisplay();
display.setCursor(0,15);
display.print("GESTOPPT");
display.display();
delay(500);
myservo.write(0);
}
if ((millis() - startTime >= duration) && digitalRead(Relais))
{
digitalWrite (Relais , LOW); // mache Relais wieder aus
Serial.print(F("FÜLLZEIT = "));
Serial.print((float)duration / 1000);
Serial.println(F(" Sek"));
Serial.println();
display.clearDisplay();
display.setCursor(0,9);
display.println("F\201LLZEIT:");
display.print((float)duration/1000);
display.print(" Sek");
display.display();
delay(500);
myservo.write(0);
delay(500);
stepper.setSpeed(400);
stepper.moveTo (325);
stepper.runToPosition();
stepper.setCurrentPosition(0);
}
drehen();
}
//======================================================================
void drehen()
{
if (!digitalRead(DrehT))
{
display.clearDisplay();
display.setCursor(0,9);
display.println("Motor dreht");
display.display();
stepper.moveTo (325);
stepper.runToPosition();
stepper.setCurrentPosition(0);
}
}
/tmp/arduino_modified_sketch_715182/sketch_feb15h.ino:37:37: warning: declaration of 'virtual void AccelStepper::disableOutputs()' outside of class is not definition [-fpermissive]
void AccelStepper::disableOutputs (); //Spulen stromlos machen um Strom zu sparen
^
Compiling libraries.
unter weiter unten die TextSize auf (1) setze,
dann habe ich zwar eine kleinere Schrift, aber keine Schmutzzeichen mehr.
Schöner wäre natürlich die größere Schrift, aber bei TExtSize (2) ist sie wieder zu groß.
Hallo Heinz,
lt Speicheranzeige verbraucht der sketch nur 75%. Und wenn ich die SSD1306 definition ändere dann passt die TextSize (2) wenn ich gleich in der 1. Zeile beginne.
Ich lass es jetzt mal so. Der Aufwand für eine andere Lösung ist (für alle die mitmachen) einfach zu groß.
Der Sketch verwendet 23128 Bytes (75%) des Programmspeicherplatzes. Das Maximum sind 30720 Bytes.
Globale Variablen verwenden 894 Bytes (43%) des dynamischen Speichers, 1154 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
Nach F: sind es immer noch 75%
Der Sketch verwendet 23228 Bytes (75%) des Programmspeicherplatzes. Das Maximum sind 30720 Bytes.
Globale Variablen verwenden 696 Bytes (33%) des dynamischen Speichers, 1352 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes
SCNR
@bertbek bei solchen Angaben unbedingt alles mitgeben.
Das führt sonst wie hier zu Verwirrungen und Fehlinterpretationen.
Dem Nano kannst Du auch den UNO-Bootloader aufspielen.
Dann gewinnst Du noch Speicherplatz....
Der Sketch verwendet 23228 Bytes (72%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
wow! Habe jetzt, wie fony vorgeschlagen, alle display.println mit FMacro versehen und ... siehe da, obwohl sich der Speicherplatz nicht geändert hat, sind die Schmutzzeichen WEG
Crazy...
Warum auch immer...
Jedenfalls DANKE nochmal an alle. Bin happy..