PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Grundsatz beim programmieren.



meddie
16.11.2013, 00:09
Hallo Leute
Habe eine grundsatzfrage. Ich bin im programmieren nicht so gut, hab zwar ein paar kleine Projekte vollzogen, aber so richtig drin bin ich nicht.
Jetzt bin ich aktuell am schreiben und stehe da vor einem kleinen Problem, was ich eigentlich immer wieder habe.
Arduino ist ja nicht Multitasking fähig, das bedeutet das mna beim coden das anders lösen muss nur wie.

Ich möchte ein UV Belichter bauen mit einem Nano, LCD und 3 Tasten. Geschaltet wird mit Relais.
So nun zum Problem ich Frage meine Taster ab, warte 10ms und Frage nochmal ab. Wenn beide high waren führe ich etwas aus. Aber jetzt möchte ich dass der Taster doppelt belegt ist drücke ich kurz macht es Befehl a drücke ich aber 2 Sekunden lang dann Befehl b. Aber ich kann doch nicht delay(2000) her nehmen dann würde er ja zwei Sekunden nix tun als warten.
Wie geht man denn so was an?
Danke im voraus für eure hilfe

PICture
16.11.2013, 00:38
Hallo!

Ich würde das beispielweise so machen, dass ich beim Drücken des Tasters einen Timer starte und nach Ablauf programmierter Zeit prüfe, ob der Taster gedrückt ist. Ein Timer läuft eben echt paralell zur CPU (Programm) und der Timer meldet sich nach Ablauf der Zeit per Interrupt. ;)

oberallgeier
16.11.2013, 09:23
Hallo meddie.

... grundsatzfrage ... Taster doppelt belegt ... kurz ... lang ...Taster kann man völlig getrennt vom Hauptprogramm betreiben. Einmal gäbs die Pollingmethode von PICture mit dem Effekt dass ein Druck zwischen zwei Timerinterrupts unbeachtet bliebe (ein Glitsch). Nun macht man solche Timerroutinen aber recht schnell. Eine andere Methode ist bei mir üblich.

Ein Timer für die "Boardzeit" mit 50 µs läuft bei praktisch allen meinen Controllern für solche und ähnliche Messungen, für Heartbeat (blinkende LED als Zeichen dass fast alles ok ist) und eben die Boardzeit = Gesamtzeit "Board seit Einschalten".

Taster hänge ich an einen externen Interrupt. Die gibts "separat" als INT0 and INT1. Die sind beispielsweise beim mega328 auf Pinn PD2 und PD3 mit der höchsten Priorisierung nach dem /RESET, sehr ähnlich bei vielen anderen Controllern. Diese Interrupts können auf steigende oder fallende Flanke oder beide eingestellt werden.

Bei vielen anderen Controllern gibt es noch die Möglichkeit jeden anderen Pinn als PCINT23...0 (wieder m328 als Beispiel) zu konfigurieren. Die Priorisierung der PCINTnn ist gleich nach den INT0 und INT1. Nicht möglich ist ein PCINTnn naturgemäß bei VCC, GND und Ähnlichen. Die PCINTnn-Interrupts triggern bei jedem Wechsel des Pinzustandes.

Was geschieht? Sobald der Interrupt anspricht lese ich den Timer aus. Timerstand wird gespeichert als z.B. "PINT1an" - Pinn von Taste 1 ist an. Man wird nach Deiner Aufgabenstellung dann noch nen Messwert bei der komplementären Flanke holen und mit dem Vergleich der beiden Messwerte die Fallunterscheidung nach "lang" oder "kurz" gedrückt machen. Etwas tricky KÖNNTE es werden, wenn Du Tastenprellen beachten MUSST - ist bei mir in mehreren Jahren eigentlich nie vorgekommen. Weiß aber nicht warum.

Thats all *ggg*. Wenn mans mal gemacht hat, total easy. Hilfen zur arduino-Umgebung gibts bei mir nicht, weil ich direkt in C programmiere.

PICture
16.11.2013, 13:06
Es wäre auch möglich den "on change interrupt", falls vorhanden, zur genauen Messung der Zeit, wie lange der Taster ununterbrochen gedrückt ist, zu verwenden.

Greensiver
16.11.2013, 18:14
Hi meddie,

erstmal vorweg, delay() ist für fast nichts zu gebrauchen als vileicht einer Zeitbegrenzten Eingabesperre:D.
Du willst ja nicht dein Programm aufhängen, sondern es soll ja weiterlaufen:). Bei solchen Anwendungen kann man sich ganz gut mit millis() behelfen (micros() get auch). millis() gibt einfach nur die Zeit an, die nach einschalten des µC vergangen ist.

Hier ein Beispielcode:




const int buttonPin = 2;
int buttonState = 0;
int sperrbyte=0;
int Befehl;
unsigned long zeit;


void setup() {
__pinMode(buttonPin, INPUT);
__digitalWrite(buttonPin, HIGH); //PullUp-Wiederstand aktivieren
}

void loop(){
__Tastenabfrage();

__if(Befehl==1){
____//Dein Code
__}
__if(Befehl==2){
____//Dein Code
__}

}

void Tastenabfrage(){
__buttonState=digitalRead(buttonPin);
__if((buttonState == LOW) && (sperrbyte==0)){
____zeit=millis(); //erste Zeit nehmen beim runterdrücken des Tasters
____sperrbyte=1; //verhindert das dauerhafte Zeitnehmen beim Tastendruck
__}
__if((buttonState == HIGH) && (zeit+60<=millis()) && (zeit+1000>millis()) && (sperrbyte==1)){ //Wenn Taster länger als 60ms (Entprellen) und kürtzer als 1 Sekunde gedrückt wurde, führe Aktion "a" aus
____Befehl=1;
____zeit=0;
____sperrbyte=0;
__}
__if((buttonState == HIGH) && (zeit+1000<=millis()) && (sperrbyte==1)){ //Wenn Taster mindestens 1 Sekunde gedrückt wurde, führe Aktion "b" aus
____Befehl=2;
____zeit=0;
____sperrbyte=0;
__}
__if((zeit+60>millis()) && (buttonState==HIGH)){ //Wen Taster kürtzer als 60ms gedrückt wurde, sperrbyte und Zeit zurücksetzen
____sperrbyte=0;
____zeit=0;
__}


}



Ich hatte keine Lust, das jetzt für 3 Buttons zu machen:).
Aber den Code wirst du ja wohl noch an deine Bedürfnisse anpassen können oder? :)


Soooo....Wen Fragen, dann fragen.


Gruß, Green

meddie
17.11.2013, 13:25
Habs kapiert! Vielen vielen Dank!!!!!!!! Besonders ein Fettes Danke für das Beispiel!!!
Gruß Eddie

meddie
18.11.2013, 22:59
Hallo Leute,

ich habe versucht das Beispiel zu übernehmen aber irgendwie mag es nicht funktionieren: Es ist so als ob die Loop nicht gestartet wird
Ich sehe am Display nur Belcihtungszeit was in der setup aufgerufen wird. Ab dann steht das Ding

Hier mein code:

/*Arduino UV Exposure Light. Built from 2 (4x9W) UV Nail Lamps placed in an old scanner.
Controlled by an Arduino Nano. 16x2 Display. A 2 Way Relais Baord 3 Buttons and
Buzzer to signal when done.
The Buttons are 'Up' 'Down' and 'Start'. When you press longer than 2 Seconds
that starts a saved time
- Up Button 45 Seconds (for Exposure a Soldering Stop Laminate)
- Down Button 3 Minutes (for exposure a PCB)
- Start Button 30 Minutes (for exposure a soldering stop laminate to get hard)

The circuit:
* LCD RS pin to digital pin D0 12
* LCD Enable pin to digital pin D1 11
* LCD D4 pin to digital pin D2 5
* LCD D5 pin to digital pin D3 4
* LCD D6 pin to digital pin D4 3
* LCD D7 pin to digital pin D5 2
* LCD R/W pin to ground
* Buzzer pin D6
* Button 1 pin D7
* Button 2 pin D8
* Button 3 pin D9
* Relais 1 pin D10
* Relais 2 pin D11
* LED pin D12

*/


// include the library code:
// LCD Lib
#include <LiquidCrystal.h>
//ToneLib for Buzzer
#include "pitches.h"


//Variable Declarations
// notes in the melody:
int melody[] = {
NOTE_C4, NOTE_G3,NOTE_G3, NOTE_A3, NOTE_G3,0, NOTE_B3, NOTE_C4};
// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
4, 8, 8, 4,4,4,4,4 };


//Hardware Pins
const int upPin = 7; //up button pin
const int startPin = 8; //start button pin
const int downPin = 9; //down button pin
int relais1Pin = 10; //relais 1 pin
int relais2Pin = 11; //relais 2 pin
int buzzerPin = 6; //piezo buzzer pin


//Variables for states
int timerCount = 0; //variable for timer setting
int minutesCount = 0; //minutes value
int secondsCount = 0; //seconds value


int buttonState = 0;
int lockbyte=0;
int command;
unsigned long time;
int pressed=0;


// initialize the LCD library with the numbers of the interface pins
LiquidCrystal lcd(0, 1, 2, 3, 4, 5);


void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print Version to the LCD.
lcd.setCursor(0,0); //set cursor to the first column and the first line
lcd.print("UV Belichter"); //print this text to LCD
lcd.setCursor(0,1); // set cursor to the first column and the second line
lcd.print("V 0.1 by meddie"); //print this Text to LCD
playTone(); //Call function playTone this will play a short meldoy
delay(3000); //wait 3 Seconds the Text will be shown 3 seconds
lcd.setCursor(0,0); //set cursor to column 1 and line 1
lcd.clear();
lcd.print("Belichtungszeit?"); //print this Text on LCD
pinMode(relais1Pin, OUTPUT);
pinMode(relais2Pin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(startPin, INPUT);
digitalWrite(startPin, HIGH); //activate PullUp
pinMode(upPin, INPUT);
digitalWrite(upPin, HIGH); //activate PullUp
pinMode(downPin, INPUT);
digitalWrite(downPin, HIGH); //aktivate PullUp
Serial.begin(9600);
}


void loop() {
//read Up button
pressed = getButtonState(upPin); //Call Buttonstate Function for upPin
//if up button pressed increment timer count and print to lcd
if(command ==1) // button is pressed less than 2 seconds
{
lcd.clear(); //clear screen
secondsCount = secondsCount+5; //increment in sec intervals
if(secondsCount==60) //increment minute & reset sec for every 60 sec
{
minutesCount++;
secondsCount=0;
}
lcdWrite(); //print values
}
if (command == 2) // button is pressed lomger than 2 seconds set the uv time to a defined seconds and start exposure
{
minutesCount=0;
secondsCount=5;
startuv();
}
//read down Button


pressed = getButtonState(downPin); //Call ButtonState function for upPin


//if down button pressed decrement timer count and print to lcd
if(command == 1)
{
lcd.clear(); //clear lcd
secondsCount = secondsCount-5; //decrement minute & reset sec for every 60 sec
if(minutesCount>0) //if more than a minute left
{
if(secondsCount==-5) // reset sec value of -5 to 55 & decrement minute
{
secondsCount=55;
minutesCount--;
}
else
{
if(secondsCount<0) //if countdown finished, reset values to zero
{
secondsCount = 0;
minutesCount = 0;
}
}
}
lcdWrite();


if(secondsCount<0)
{
secondsCount=0;
lcd.clear();
lcd.print("0");
}
}
if (command == 2) // button is pressed longer than 2 seconds set the uv time to a defined seconds and start exposure
{
minutesCount=0;
secondsCount=10;
startuv();
}
//read start button
pressed = getButtonState(startPin);
if (command == 1) // button is pressed less than 2 seconds start the exposure with the entered time
{
startuv();
}
if (command == 2) // button is pressed lomger than 2 seconds set the uv time to a defined seconds and start exposure
{
minutesCount=0;
secondsCount=1;
startuv();
}
}




//if start button pressed activate relais 1 and 2
//print timer count down to lcd
//activate buzzer to signal end of count
void startuv() {


timerCount = (minutesCount*60) + secondsCount;
int timerCount2 = timerCount;
Serial.println(timerCount);
for(int i=timerCount;i>0;i--)
{
lcd.clear();


if(timerCount2>60)
{
minutesCount = timerCount2/60;
secondsCount = timerCount2%60;
}
else if(secondsCount==60)
{
secondsCount=59;
}
else
{
minutesCount = 0;
secondsCount = timerCount2;
}




lcdWrite();


//send transistor base pin high
digitalWrite(relais1Pin, HIGH);
digitalWrite(relais2Pin, HIGH);
delay(1000);
timerCount2--;
}


lcd.clear();
lcd.print("Fertig");


//turn transistor off
digitalWrite(relais1Pin, LOW);
digitalWrite(relais2Pin, LOW);


//Play Tone on Buzzer
playTone();
delay(2000);


lcd.clear();
lcd.print("Belcihtungszeit?");


//reset timer values
timerCount = 0;
minutesCount = 0;
secondsCount = 0;
command=0;
}


void playTone() {
// iterate over the notes of the melody:
for (int thisNote = 0; thisNote < 8; thisNote++) {


// to calculate the note duration, take one second
// divided by the note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
int noteDuration = 1000/noteDurations[thisNote];
tone(buzzerPin, melody[thisNote],noteDuration);


// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// stop the tone playing:
noTone(buzzerPin);
}
}


void lcdWrite()
{
lcd.setCursor(0, 0); //set cursor to top left
lcd.print(minutesCount); //print minutes value
lcd.setCursor(3, 0); //set cursor on other side of minutes value
lcd.print("Min"); //print min string
lcd.setCursor(7, 0); //set cursor further right
lcd.print(secondsCount); //print seconds value
lcd.setCursor(10,0); //set cursor further right
lcd.print("Sek"); //print sec string
}


int getButtonState(const int buttonPin){
buttonState=digitalRead(buttonPin);
if((buttonState == LOW) && (lockbyte==0)){ //buttonPin is defined as High, that means that the internal Pull-Up is On. When button is pressed than the buttonPin will change from HIGH to LOW
time=millis(); // take a time when button is pressed
lockbyte=1; //lockbyte prevents that the time will stopped on each buttonpress
}
if((buttonState == HIGH) && (time+60<=millis()) && (time+2000>millis()) && (lockbyte==1)){ // When Button is pressed longes thab 60ms (debounce) and Button is pressed less than 2000 millis (2 Second), do command "a"
command=1; //1 = button is pressed less than 2 seconds
time=0; //reset time to 0
lockbyte=0; //reset the lockbyte
}
if((buttonState == HIGH) && (time+2000<=millis()) && (lockbyte==1)){ //When Button is pressed longer as 2 Seconds do command "b"
command=2; //2 = button is pressed longer then 2 seconds
time=0; // reset time to 0
lockbyte=0; //reset the lockbyte
}
if((time+60>millis()) && (buttonState==HIGH)){ // When Buttons is pressed less than 60ms, then reset lockbyte and time to 0
lockbyte=0; //reset lockbit to 0
time=0; //reset time to 0
}
return command;
}




Hat da jemand eine Idee was ich falsch gemacht habe?
danke im Voraus

meddie
19.11.2013, 22:29
Hallo Leute, ich konnte es ein wenig eingrenzen aber noch nicht ausfindig machen. In der Loop rufe ich drei mal die Funktion getButtonState auf. Einmal zum abfragen des pin 7 dann 9 dann 8. Das sind von mir drei befehlbereiche. wenn ich jeweils 2 rauslösche und immer nur einen teste also den ganzen abschnitt für den upButton dann klappt alles. also alle drei Buttons einzeln funktionieren. Allerdings nicht wenn ich alle 3 buttons drin habe dann hängt es.

Der Code sieht jetzt so aus:

/*Arduino UV Exposure Light. Built from 2 (4x9W) UV Nail Lamps placed in an old scanner.
Controlled by an Arduino Nano. 16x2 Display. A 2 Way Relais Baord 3 Buttons and
Buzzer to signal when done.
The Buttons are 'Up' 'Down' and 'Start'. When you press longer than 2 Seconds
that starts a saved time
- Up Button 45 Seconds (for Exposure a Soldering Stop Laminate)
- Down Button 3 Minutes (for exposure a PCB)
- Start Button 30 Minutes (for exposure a soldering stop laminate to get hard)

The circuit:
* LCD RS pin to digital pin D0 12
* LCD Enable pin to digital pin D1 11
* LCD D4 pin to digital pin D2 5
* LCD D5 pin to digital pin D3 4
* LCD D6 pin to digital pin D4 3
* LCD D7 pin to digital pin D5 2
* LCD R/W pin to ground
* Buzzer pin D6
* Button 1 pin D7
* Button 2 pin D8
* Button 3 pin D9
* Relais 1 pin D10
* Relais 2 pin D11
* LED pin D12

*/


// include the library code:
// LCD Lib
#include <LiquidCrystal.h>
//ToneLib for Buzzer
#include "pitches.h"


//Variable Declarations
// notes in the melody:
int melody[] = {
NOTE_C4, NOTE_G3,NOTE_G3, NOTE_A3, NOTE_G3,0, NOTE_B3, NOTE_C4};
// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
4, 8, 8, 4,4,4,4,4 };


//Hardware Pins
const int upPin = 7; //up button pin
const int startPin = 8; //start button pin
const int downPin = 9; //down button pin
int relais1Pin = 10; //relais 1 pin
int relais2Pin = 11; //relais 2 pin
int buzzerPin = 6; //piezo buzzer pin


//Variables for states
int timerCount = 0; //variable for timer setting
int minutesCount = 0; //minutes value
int secondsCount = 0; //seconds value


int buttonState = 0;
int lockbyte=0;
int command;
unsigned long time;
int pressed=0;


// initialize the LCD library with the numbers of the interface pins
LiquidCrystal lcd(0, 1, 2, 3, 4, 5);


void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print Version to the LCD.
lcd.setCursor(0,0); //set cursor to the first column and the first line
lcd.print("UV Belichter"); //print this text to LCD
lcd.setCursor(0,1); // set cursor to the first column and the second line
lcd.print("V 0.1 by meddie"); //print this Text to LCD
playTone(); //Call function playTone this will play a short meldoy
delay(3000); //wait 3 Seconds the Text will be shown 3 seconds
lcd.setCursor(0,0); //set cursor to column 1 and line 1
lcd.clear();
lcd.print("Belichtungszeit?"); //print this Text on LCD
pinMode(relais1Pin, OUTPUT);
pinMode(relais2Pin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(startPin, INPUT);
digitalWrite(startPin, HIGH); //activate PullUp
pinMode(upPin, INPUT);
digitalWrite(upPin, HIGH); //activate PullUp
pinMode(downPin, INPUT);
digitalWrite(downPin, HIGH); //aktivate PullUp
Serial.begin(9600);
}


void loop() {
//read Up button
pressed = getButtonState(upPin); //Call Buttonstate Function for upPin
//if up button pressed increment timer count and print to lcd
if (command == 1 ) // button is pressed less than 2 seconds
{
lcd.clear(); //clear screen
secondsCount = secondsCount+5; //increment in sec intervals
if (secondsCount == 60) //increment minute & reset sec for every 60 sec
{
minutesCount++;
secondsCount=0;
}
lcdWrite(); //print values
command=0;
}
if (command == 2) // button is pressed lomger than 2 seconds set the uv time to a defined seconds and start exposure
{
minutesCount=0;
secondsCount=5;
startuv();
command=0;
}
//read down Button
pressed = getButtonState(downPin); //Call ButtonState function for upPin


//if down button pressed decrement timer count and print to lcd
if (command == 1)
{
lcd.clear(); //clear lcd
secondsCount = secondsCount-5; //decrement minute & reset sec for every 60 sec
if(minutesCount>0) //if more than a minute left
{
if(secondsCount==-5) // reset sec value of -5 to 55 & decrement minute
{
secondsCount=55;
minutesCount--;
}
else
{
if(secondsCount<0) //if countdown finished, reset values to zero
{
secondsCount = 0;
minutesCount = 0;
}
}
}
lcdWrite();
command=0;
if(secondsCount<0)
{
secondsCount=0;
lcd.clear();
lcd.print("0 Min 0 Sek");
}
}
if (command == 2) // button is pressed longer than 2 seconds set the uv time to a defined seconds and start exposure
{
minutesCount=0;
secondsCount=10;
startuv();
command=0;
}
//read start button
pressed = getButtonState(startPin);
if (command == 1) // button is pressed less than 2 seconds start the exposure with the entered time
{
startuv();
command=0;
}
if (command == 2) // button is pressed lomger than 2 seconds set the uv time to a defined seconds and start exposure
{
minutesCount=0;
secondsCount=1;
startuv();
command=0;
}
}




//if start button pressed activate relais 1 and 2
//print timer count down to lcd
//activate buzzer to signal end of count
void startuv() {


timerCount = (minutesCount*60) + secondsCount;
int timerCount2 = timerCount;
Serial.println(timerCount);
for(int i=timerCount;i>0;i--)
{
lcd.clear();


if(timerCount2>60)
{
minutesCount = timerCount2/60;
secondsCount = timerCount2%60;
}
else if(secondsCount==60)
{
secondsCount=59;
}
else
{
minutesCount = 0;
secondsCount = timerCount2;
}




lcdWrite();


//send transistor base pin high
digitalWrite(relais1Pin, HIGH);
digitalWrite(relais2Pin, HIGH);
delay(1000);
timerCount2--;
}


lcd.clear();
lcd.print("Fertig");


//turn transistor off
digitalWrite(relais1Pin, LOW);
digitalWrite(relais2Pin, LOW);


//Play Tone on Buzzer
playTone();
delay(2000);


lcd.clear();
lcd.print("Belcihtungszeit?");


//reset timer values
timerCount = 0;
minutesCount = 0;
secondsCount = 0;
command=0;
}


void playTone() {
// iterate over the notes of the melody:
for (int thisNote = 0; thisNote < 8; thisNote++) {


// to calculate the note duration, take one second
// divided by the note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
int noteDuration = 1000/noteDurations[thisNote];
tone(buzzerPin, melody[thisNote],noteDuration);


// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// stop the tone playing:
noTone(buzzerPin);
}
}


void lcdWrite()
{
lcd.setCursor(0, 0); //set cursor to top left
lcd.print(minutesCount); //print minutes value
lcd.setCursor(3, 0); //set cursor on other side of minutes value
lcd.print("Min"); //print min string
lcd.setCursor(7, 0); //set cursor further right
lcd.print(secondsCount); //print seconds value
lcd.setCursor(10,0); //set cursor further right
lcd.print("Sek"); //print sec string
}


int getButtonState(const int buttonPin){
buttonState=digitalRead(buttonPin);
if((buttonState == LOW) && (lockbyte==0)){ //buttonPin is defined as High, that means that the internal Pull-Up is On. When button is pressed than the buttonPin will change from HIGH to LOW
time=millis(); // take a time when button is pressed
lockbyte=1; //lockbyte prevents that the time will stopped on each buttonpress
}
if((buttonState == HIGH) && (time+60<=millis()) && (time+2000>millis()) && (lockbyte==1)){ // When Button is pressed longes thab 60ms (debounce) and Button is pressed less than 2000 millis (2 Second), do command "a"
command=1; //1 = button is pressed less than 2 seconds
time=0; //reset time to 0
lockbyte=0; //reset the lockbyte
}
if((buttonState == HIGH) && (time+2000<=millis()) && (lockbyte==1)){ //When Button is pressed longer as 2 Seconds do command "b"
command=2; //2 = button is pressed longer then 2 seconds
time=0; // reset time to 0
lockbyte=0; //reset the lockbyte
}
if((time+60>millis()) && (buttonState==HIGH)){ // When Buttons is pressed less than 60ms, then reset lockbyte and time to 0
lockbyte=0; //reset lockbit to 0
time=0; //reset time to 0
}
return command;
}