Pages: 1 [2]   Go Down
Author Topic: Anfänger braucht Hilfe mit uno  (Read 1629 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Was hast Du denn als LCD?

ich habe das aufsteck lcd mit den 6 Tasten, habe auch weiter oben einen link zu dem bild eingefügt.
Logged

Germany S-H
Offline Offline
Faraday Member
**
Karma: 164
Posts: 3198
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Was hast Du denn als LCD?

ich habe das aufsteck lcd mit den 6 Tasten, habe auch weiter oben einen link zu dem bild eingefügt.

Dann hast Du ja wenig zu basteln und brauchst nur die beiden Reedkontakte anschließen.

Du kannst ja mal zusehen, ob Du in der loop-Funktion aus "roundStart1" und einer Hilfsvariablen die Rundenzeiten selbst herausbekommst, wenn sich der Wert von "roundStart1" ändert.

Ich muß jetzt erstmal einkaufen fürs Wochenende und kann mir dann nachher nochmal ein paar Gedanken dazu machen.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

wäre nett wenn du mir da nochmal Hilfestellung leisten könntest.

baue jetzt mal auf dem script vom Kollegen jurs auf:

Code:
#define LEDPIN 13  /das wirds der pin sein der meine led blinken lässt?!
#define REEDPIN1 2         /der Eingang der als erste von zwei Interrupts an Pin 2 fungiert?!
#define REEDINTERRUPT1 0
long roundStart1=-9999;   verstehe ich noch nicht

denke das ich das ganze zweimal machen muss wegen der zwei eingänge, versuche das mal in einem script einzubauen

void setup() {
  // put your setup code here, to run once:
  pinMode(LEDPIN,OUTPUT);
  pinMode(REEDPIN1,INPUT_PULLUP);
  attachInterrupt(REEDINTERRUPT1, timing1, CHANGE);
}

void timing1()
{
  boolean static lastState;
  boolean state;
  state=digitalRead(REEDPIN1);
  if (state!=lastState && state==LOW)
    roundStart1=millis();
  lastState=state; 
}

void loop()
{
  if (millis()-roundStart1<500)
    digitalWrite(LEDPIN,HIGH);
  else 
    digitalWrite(LEDPIN,LOW);
}


jetzt mal mein abgeändertes Script:

Code:
#define LEDPIN 13
#define REEDPIN1 2
#define REEDINTERRUPT1 0
long roundStart1=-9999;

#define LEDPIN 14               /tu jetzt mal so als würde es die LED mit pin 14 geben für den zweiten Reed Kontakt
#define REEDPIN2 3
#define REEDINTERRUPT2 1
long roundStart1=-9999;
Logged

Germany S-H
Offline Offline
Faraday Member
**
Karma: 164
Posts: 3198
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

wäre nett wenn du mir da nochmal Hilfestellung leisten könntest.

Ich bin dann mal so nett.

Das mit der Interruptprogrammierung geht natürlich weit über "Anfängerprogrammierung" hinaus. Aber ohne die Nutzung von Interrupts ist es für Deinen Anwendungsfall kaum sinnvoll zu realisieren, wenn man nicht "verschluckte" Runden riskieren möchte. Mit typischer Anfängerprogrammierung ist Dein Anwendungsfall leider nicht perfekt in Software umsetzbar, sondern nur mit fortgeschrittenen Programmiertechniken und Nutzung der Hardware-Interrupts.

Als Goodies außerhalb Deiner Spezifikation habe ich gleich nochmal einen "Rundenzähler" eingebaut und eine Anzeige, die im Zweisekundentakt wechselt zwischen "Anzeige der Rundenzeiten" und "Anzeige der Rundenanzahl".

Vollständig unter Echtbedingungen testen kann ich natürlich nicht, da ich weder die Rennbahn noch die Reedkontakte habe.

Das Timing selbst ist bis hin zur Verarbeitung übrigens auf tausendstel Sekunden genau und erst beim Anzeigen der Zeiten wird auf hundertsel Sekunden gerundet.

Probier's aus, ob Du was damit anfangen kannst!

Damit Du ggf. selbst Änderungen vornehmen kannst, habe ich einige Kommentarzeilen dazugeschrieben und mich bemüht, sprechende Variablennamen zu vergeben, die von selbst erklären, was darin gespeichert ist.

Außerdem habe ich das Programm gleich so angelegt, daß man es mit möglichst geringem Aufwand auf bis zu sechs Slot-Zeitmessungen erweitern könnte, falls man es auf ein MEGA Board (mit 6 Interrupts) umschreiben und erweitern möchte.

Code:
/*
   Slotcar timing by "jurs" for German Arduino forum
   Hardware required: Arduino UNO, LCD keypad shield, 2 reed contacts
*/
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // Sainsmart keypad LCD

#define LEDPIN 13
#define SLOTS 2
// Mindestrundenzeit in Millisekunden, alles darunter als Kontaktprellen interpretieren
#define MINROUNDTIME 500
// Pins zum Anschluss der Reedkontakte (D2, D3)
byte reedPins[]={2,3};
// Interrupt-Nummern zu diesen Pins
byte pinInterrupts[]={0,1};
// Interrupt-Behandlungsroutinen
void (*isrFunctions[])() = { timing1, timing2 };

// Start der letzten Runde in Millisekunden, volatile weil Zugriff auch aus ISR!
volatile long rundenAnfang[]={0,0};
// Rundenzeit der letzten Runde in Millisekunden
long rundenZeit[]={99990,99990};
// Rundenzeit der schnellsten Runde in Millisekunden
long rundenZeitRekord[]={99990,99990};
// Rundenzähler
int rundenAnzahl[]={0,0};


void setup() {
  // LCD Anzeige mit Spalten und Zeilen initialisieren
  lcd.begin(16, 2);
  // Anzeige LED-13 auf dem Board initialisieren
  pinMode(LEDPIN,OUTPUT);
  // Reedkontakte und ISR Routinen initialisieren
  for (int i=0;i<SLOTS;i++)
  {
    pinMode(reedPins[i],INPUT_PULLUP);
    attachInterrupt(pinInterrupts[i], isrFunctions[i], FALLING);
  } 
}

void timing1()
{
  if (millis()-rundenAnfang[0]>MINROUNDTIME)
    rundenAnfang[0]=millis();
}

void timing2()
{
  if (millis()-rundenAnfang[1]>MINROUNDTIME)
    rundenAnfang[1]=millis();
}

void RundenzeitenVerarbeiten()
{
  // Start der vorletzten Runde in Millisekunden
  static long rundenAnfangVerarbeitet[]={0,0};
  long curMillis;
  // Aktuellen Stand der millis() Funktion merken
  curMillis=millis();
  // Alle Slots auf Veränderungen der Rundenstartzeit abklappern
  for (int i=0;i<SLOTS;i++)
  {
    if  (rundenAnfangVerarbeitet[i]!=rundenAnfang[i])
    { // Neue Runde seit dem letzten Loopdurchlauf
      rundenAnzahl[i]++; // Rundenzähler hochzählen
      // Rundenzeit ermitteln
      rundenZeit[i]=rundenAnfang[i]-rundenAnfangVerarbeitet[i];
      // Feststellen ob es eine schnellste Runde war
      if (rundenZeit[i]<rundenZeitRekord[i])
        rundenZeitRekord[i]=rundenZeit[i];
      // Am Ende diese Rundenzeit als verarbeitet merken 
      rundenAnfangVerarbeitet[i]=rundenAnfang[i];
    }
  }
}

void RundenanzahlAnzeigen()
{ static long lastUpdate;
  char lcdline[17];
  // Anzeige nur alle 500 ms aktualisieren
  if (millis()/500==lastUpdate) return;
  lastUpdate=millis()/500;
  for (int i=0;i<SLOTS;i++)
  {
    snprintf(lcdline,sizeof(lcdline),"%d %5d Runden  ",i+1,rundenAnzahl[i]);
    lcd.setCursor(0,i);
    lcd.print(lcdline);
  } 
}

void RundenzeitenAnzeigen()
{ static long lastUpdate;
  long dieseRunde, dieserRekord;
  char lcdline[17];
  int zeit[4];
  // Anzeige nur alle 500 ms aktualisieren
  if (millis()/500==lastUpdate) return;
  lastUpdate=millis()/500;
  for (int i=0;i<SLOTS;i++)
  {
    // Rundenzeit und schnellste Zeit auf Zeitangabe in hundertstel runden
    dieseRunde=(rundenZeit[i]+5)/10;
    dieserRekord=(rundenZeitRekord[i]+5)/10;
    zeit[0]=dieseRunde/100; // ganze Sekunden
    zeit[1]=dieseRunde%100; // hundertstel Sekunden
    zeit[2]=dieserRekord/100;  // ganze Sekunden
    zeit[3]=dieserRekord%100; // hundertstel Sekunden
    snprintf(lcdline,sizeof(lcdline),"%d%3d:%02d SR%3d:%02d",i+1,zeit[0],zeit[1],zeit[2],zeit[3]);
    lcd.setCursor(0,i);
    lcd.print(lcdline);
  } 
}

void loop()
{
  RundenzeitenVerarbeiten();
  if ((millis()/2000)%2==1)
    RundenzeitenAnzeigen();
  else
    RundenanzahlAnzeigen(); 
  // Nun noch die Pin-13 LED ein wenig blinken lassen, wenn man möchte 
  if (millis()-rundenAnfang[0]<200 || millis()-rundenAnfang[1]<200)
    digitalWrite(LEDPIN,HIGH);
  else 
    digitalWrite(LEDPIN,LOW); 
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

vielen vielen Dank jurs,

habe es gestern Abend noch umgesetzt und es funktionieret super...echt geil wie du das mit dem umschwenken auf die zweite Ebene gemacht hast wäre ich erstmal gar nicht drauf gekommen smiley-wink

Jedenfalls kommen mein Sohn und mein Enkel heute und wir werden viel Spass haben, kannst sicher sein das Dein Name fällt smiley-wink

Danke nochmal

jetzt habe ich noch einen Grund mehr mich mit der Programmierung zu beschäftigen....Es ist ein geiles Zeug
Logged

Germany S-H
Offline Offline
Faraday Member
**
Karma: 164
Posts: 3198
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

habe es gestern Abend noch umgesetzt und es funktionieret super...echt geil wie du das mit dem umschwenken auf die zweite Ebene gemacht hast wäre ich erstmal gar nicht drauf gekommen smiley-wink

Ich habe mir gedacht, dass die Anzeige etwas zu langweilig aussieht, wenn sie immer nur dieselben Werte anzeigt. Beim Autorennen ist ja Action angesagt, da kann etwas Action auf der Anzeigetafel auch nicht schaden und ich habe daher die Wechselanzeige realisiert, mit automatischer Umschaltung alle zwei Sekunden zwischen Rundenzeiten und Rundenanzahl.

Nacheinander angezeigt kann man ja mehr Werte darstellen als sie auf einmal ins Display passen.

Jedenfalls kommen mein Sohn und mein Enkel heute und wir werden viel Spass haben,

Na dann viel Spass mit Kind und Enkel beim Autorennen!

Ganz schön gemischtes Publikum hier im Forum, vom Schulkind bis zum Opa alles dabei.

Nochmal was mir gerade zu den Reedkontakten einfällt, ich habe mir mal im Internet angesehen, wie andere die Kontakte in ihre Bahn einbauen:
http://hackadaycom.files.wordpress.com/2011/06/sensors.jpg?w=1000&h=
Dort sind noch zusätzliche kleine Kondensatoren parallel zu den Reedkontakten geschaltet, mit denen offenbar Kontaktprellen vermieden werden soll. Diese Kondensatoren brauchst Du natürlich nicht, denn im Programm wird Kontaktprellen softwaretechnisch unterdrückt, über die mit 500 Millisekunden extrem lang festgelegte MINROUNDTIME. Durch die Kondensatoren sinkt höchstens die Lebensdauer der Kontakte, denn Reedkontakte sind leider Verschleißteile und nach einigen Millionen Schließvorgängen werden sie meistens defekt. Also die Kondensatoren würde ich lieber weglassen und nur die Reedkontakte einbauen.

jetzt habe ich noch einen Grund mehr mich mit der Programmierung zu beschäftigen....Es ist ein geiles Zeug

Dann mal zu!

Denn im Endeffekt ist Dein neuer Slotcar-Renncomputer mit dem Programm noch lange nicht ausgelastet, der könnte noch viel mehr. Bis auf die Reset-Taste zum Neustart werden die übrigen Tasten des Keypad-Shields noch gar nicht verwendet und es sind noch etliche Ein-/Ausgänge am Arduino frei.

Z.B. könnte man das Teil zum Startcomputer erweitern: Man könnte z.B. einen Piezo-Piepser oder einige LEDs als "Rennampel" anschließen, beim Drücken auf "Select" könnte dann eine Startsequenz ablaufen an deren Ende der Start signalisiert wird. Wenn man die Rennwagen direkt vor der Start-/Ziellinie mit dem Reedkontakt platziert (Rundenzahl dann am besten auf -1 initialisieren, beim Überfahren der Startlinie springt die Rundenzahl auf 0), könnten dann auch "Frühstarts" einwandfrei erkannt werden, wenn nämlich der Wagen eines Fahrers beim Start den Reedkontakt auslöst, noch bevor das Startsignal gegeben wurde. Der Frühstarter könnte dann vom Arduino automatisch eine Strafrunde aufgebrummt bekommen, oder eine Strafzeit.

Und auch für das Rennende könnte man es verwenden: Wenn man beispielsweise vor Rennbeginn festlegt, wieviele Runden gefahren werden sollen (einstellbar über die Tasten), könnte der Arduino das Rennende ermitteln (wenn der erste Fahrer seine Rundenzahl absolviert hat), die Gesamtzeit ermitteln und feststellen, um wieviel die Nachfolgenden hinterherhängen.

Erweiterungsmöglichkeiten sind also noch vorhanden.  smiley-wink
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

genauso habe ich mir das auch gedacht smiley-wink

das wird aber noch ein weiter Weg für mich sein....der aber verdammt viel Spass macht.

Eine Frage noch....wenn ich das Script grafisch auf dem PC wiedergeben möchte, muss ich dann ein Network Shield haben oder kann ich direkt über den am USB angeschlossenen Controllerdie Daten abfragen und weiter reichen?


Danke nochmal und ein schönes Rest Wochenende
Logged

Germany S-H
Offline Offline
Faraday Member
**
Karma: 164
Posts: 3198
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Eine Frage noch....wenn ich das Script grafisch auf dem PC wiedergeben möchte, muss ich dann ein Network Shield haben oder kann ich direkt über den am USB angeschlossenen Controllerdie Daten abfragen und weiter reichen?

Grafische Darstellungen auf dem Arduino zu erstellen, dürfte sehr schwierig werden, denn Grafiken belegen sehr viel Speicherplatz und der Arduino hat nur 2 KB RAM zur Verfügung. Das wird wohl eher nichts.

Was einfach machbar ist und auch über USB-Anschluß am PC funktioniert, ist das Übertragen der Daten per serieller Schnittstelle an den PC.

Im einfachsten Fall machst Du einfach einen seriellen Zeilenticker, der zeilenweise Daten darstellen kann. Dazu einfach in der Arduino-Software den seriellen Monitor öffnen, in der Setup-Funktion die serielle Schnittstelle initialisieren und per Serial.print() bzw. Serial.println() die gewünschten Daten an den PC senden. Dasselbe USB-Kabel, über das der Programmsketch auf den PC geladen wird kann auch dazu dienen, aus dem laufenden Programm heraus Text und Daten an den PC zu senden.

Aus dem Textfenster des Terminals könntest Du die gesendeten Daten und Auswertungen dann auch herauskopieren und ausdrucken oder abspeichern, so dass die Daten später noch nachlesbar sind.

Wenn es ein bischen hübscher dargestellt werden soll als per Zeilenticker, bunt und in Farbe, dann gäbe es die Möglichkeit ein Terminalprogramm auf dem PC laufen zu lassen. Also beispielsweise Hyperterm unter Windows, Putty, oder eines der vielen seriellen Terminalprogramme. Dann könnte man über den Arduino nicht nur einfach Text und Daten senden, sondern auch Steuerzeichen: Zum Setzen von Hintergrund- und Vordergrundfarbe, Positionierung des Cursors, Löschen und Neuaufbauen des Bildschirms etc. So daß man zur Darstellung statt 16 Zeichen mal 2 Zeilen in monochrom auf dem Display dann 80 Zeichen mal 25 Zeilen in 16 Farben auf einem PC-Monitor im Terminalprogramm zur Verfügung hat.

Wenn die Darstellung auf dem PC-Monitor noch toller werden soll als es mit einem Terminal möglich ist, mußt Du wahrscheinlich zur Darstellung auf dem PC auch noch ein PC-Programm programmieren. Dann sendet der Arduino die Daten an den PC, der PC liest die Daten mit dem speziell dafür programmierten Programm von der seriellen Schnittstelle und stellt sie so dar wie man es möchte.

Eine Ethernet-Shield Netzwerkkarte benötigt man für den Arduino dafür nicht. Die wäre erst dann empfehlenswert, wenn man die Daten live ins Internet senden möchte, sagen wir mal Du betreibst eine Livestream-Webcam zur Übertragung Deiner Rennen ins Internet und möchtest auf einer Webseite gleichzeitig das Live-Bild einbinden, aber auch die Renndaten sollen auf der Webseite live neben oder unterhalb des Videostream dargestellt werden.
Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1419
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Eine Frage noch....wenn ich das Script grafisch auf dem PC wiedergeben möchte, muss ich dann ein Network Shield haben oder kann ich direkt über den am USB angeschlossenen Controllerdie Daten abfragen und weiter reichen?
Für diesen Fall bietet sich Processing an (http://www.processing.org/). Die Arduino IDE basiert im übrigen auf dieser Software, was die Einarbeitung vereinfachen sollte. Mit Processing kann man sehr einfach grafische Ausgaben erzeugen z.B. Diagramme o.ä.
Es gibt sehr viele Beispiele im Netz, die eine Anbindung des Arduino an Processing mittels der seriellen Schnittstelle über USB realisieren. Der Arduino sendet einfach nur Daten über die serielle Schnittstelle und Processing kümmert sich dann (entsprechend programmiert natürlich) um die grafische Aufarbeitung der Daten. In Processing könnte man so z.B. eine richtig große Rundentafel auf den Monitor zaubern.
Mario.
Logged

Pages: 1 [2]   Go Up
Jump to: