train control project

Als U een gezamenlijk project wil starten of aan projecten van anderen mee wilt werken.
Berichten: 4067
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: train control project

Berichtdoor shooter » 18 Sep 2016, 16:43

afronden kun je doen met int(floatgetal).
en er staan nog steeds delays in dus je loop duurt te lang waardoor er voorbij gereden wordt.
paul deelen
shooter@home.nl

Advertisement

Gebruikers-avatar
Berichten: 31
Geregistreerd: 08 Sep 2016, 21:50

Re: train control project

Berichtdoor Kitemasters » 27 Sep 2016, 00:08

ok...nieuwe opzet (zonder delay)

rijdt nu al een uurtje heen en weer
en nog geen poortje gemist. :-)
kan nog wel wat gesleuteld worden aan de snelheid.

cpp code
/*
Train control
Drive the train between two gates made of a LED and LDR.
*/
// --------CONSTANTS (won't change)---------------

const byte sensL = A4; // the pin number for ldr L
const byte sensR = A5; // the pin number for ldr R
const byte led_L_Pin = 4; // the pin number for the L LED
const byte led_R_Pin = 5; // the pin number for the R LED
const byte motor_Pin = 3; // the pin number for the motor speed
const byte brake_Pin = 9; // the pin number for the motor brake
const byte direction_Pin = 12; // the pin number for the motor direction

const int read_sens_Interval = 200; // millisecs between reading sensors
const int motor_Acc_Interval = 100; // millisecs between acceleration steps
const int motor_Dec_Interval = 100; // millisecs between deceleration steps

//------------ VARIABLES (will change)---------------------

unsigned long currentMillis = 0; // stores the value of millis() in each iteration of loop()
unsigned long previous_sens_Millis = 0; // will store the last time sensors are read
unsigned long previous_state_Millis = 0; // will store the last time state is printed
unsigned long previous_Acc_Millis = 0; // will store time of last acceleration step
unsigned long previous_Dec_Millis = 0; // will store time of last deceleration step

int sensLreading = 0; //variable voor de waarde van sensL
int sensRreading = 0; //variable voor de waarde van sensR
byte max_Speed = 200; //declare variable and set value for maximum Speed (0 to 255)
byte Speed = 0; //declare variable and set value for current Speed (0 to 255)
boolean direct = true; //declare variable and set value for driving direction
String state = String("start"); //declare variable and set value for state

//========================================

void setup() {

Serial.begin(9600);

pinMode(led_L_Pin, OUTPUT); // set led_L_Pin as output
pinMode(led_R_Pin, OUTPUT); // set led_R_Pin as output
pinMode(motor_Pin, OUTPUT); // set motor_Pin as output
pinMode(brake_Pin, OUTPUT); // set brake_Pin as output
pinMode(direction_Pin, OUTPUT); // set direction_Pin as output

// pinMode(sensL, INPUT); // not needed cousse analogread is always input?
// pinMode(sensR, INPUT); // not needed cousse analogread is always input?

}
//========================================

void loop() {

currentMillis = millis(); // capture the latest value of millis()

read_sens(); // read the sensors

if (state == "start") {
Start();
}

if (state == "accelerate") {
Accelerate();
}

if (state == "decelerate") {
Decelerate();
}
}
//========================================

void read_sens() {

if (currentMillis - previous_sens_Millis >= read_sens_Interval) { // time is up, so read sensors
sensLreading = analogRead(sensL); // read left ldr (high value means the light is off or blockt)
//Serial.print("Left = "); // print for debug
//Serial.println(sensLreading); // print for debug
sensRreading = analogRead(sensR); // read right ldr (high value means the light is off or blockt)
//Serial.print("Right = "); // print for debug
//Serial.println(sensRreading); // print for debug
previous_sens_Millis += read_sens_Interval; // and save the time we last read sensors

if (sensLreading > 200 && direct == true) { //if conditions are throu, the train reached left gate***
digitalWrite(led_L_Pin, LOW); //Turn left LED off
digitalWrite(led_R_Pin, HIGH); //Turn right LED on
state = String("decelerate"); // set state to "decelerate"
}

if (sensRreading > 200 && direct == false) { //if conditions are throu, the train reached right gate***
digitalWrite(led_R_Pin, LOW); //Turn right LED off
digitalWrite(led_L_Pin, HIGH); //Turn left LED on
state = String("decelerate"); // set state to "decelerate"
}
}
}
//========================================

void Start() {

digitalWrite(led_L_Pin, HIGH); // turn left led on
digitalWrite(brake_Pin, LOW); // Disengage the Brake
digitalWrite(direction_Pin, LOW); // Establishes left direction of train
state = String("accelerate"); // set state to "accelerate"
direct = true; // set direction to true (true = LOW = left)
}
//========================================

void Accelerate() {

if (currentMillis - previous_Acc_Millis >= motor_Acc_Interval) { // time is up, so accelerate
Speed = Speed + 1; // add 1 to speed
analogWrite(motor_Pin, Speed); // send Speed to motor_Pin
Serial.print("Speed = "); // print for debug
Serial.println(Speed); // print for debug
previous_Acc_Millis += motor_Acc_Interval; // last time of acceleration step
if (Speed == max_Speed){ // if speed reach max speed
state = String("run"); // set state to "run"
}
}
}
//========================================

void Decelerate() {

if (currentMillis - previous_Dec_Millis >= motor_Dec_Interval) { // time is up, so decelerate
Speed = Speed - 1; // subtract 1 of speed
analogWrite(motor_Pin, Speed); // send Speed to motor_Pin
Serial.print("Speed = "); // print for debug
Serial.println(Speed); // print for debug
previous_Dec_Millis += motor_Dec_Interval; // last time of deceleration step
if (Speed == 0){
if (direct == true){ // flip direction
direct = false;
digitalWrite(direction_Pin, HIGH); // Establishes right direction of train
}
else {
direct = true;
digitalWrite(direction_Pin, LOW); // Establishes left direction of train
}
state = String("accelerate"); // dit gaat er uit
}
}
}
//========================================END

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: train control project

Berichtdoor Koepel » 27 Sep 2016, 01:51

Mooi :D Ik hou van een state machine met millis() :D

Bedoel je met de snelheid de snelheid van het versnellen en vertragen ?
Je hebt nu 100ms interval voor een snelheid tussen 0 en 200. Dat duurt dus 20 seconden. Dat is best veel.
Je kunt de snelheid met 2 of meer verhogen. Dan zou ik een integer van de speed maken, en de test op maximum in minimum anders doen.
Code: Alles selecteren
int Speed;

if( Speed >= max_Speed)
  ...

if( Speed <= 0)
  ...

Dan bouw je een extra zekerheid in, door '>=' en '<=' te gebruiken. Maar dan moet 'Speed' wel een integer zijn.

Je gebruikt consequent "unsigned long" voor de currentMillis en de verschillende previousMillis, en de berekening is consequent currentMillis - previousMillis. Dat is heel goed :D

Er staat voldoende commentaar bij :) Je zou de header nog wat kunnen uitbreiden, bijvoorbeeld voor welk type Arduino het is, met welke versie van de Arduino IDE, en de datum erbij.

Ik kan nog wel een paar opmerkingen geven als je het goed vindt.

Ik vind het belangrijk om alle haakjes en het inspringen altijd op dezelfde manier te doen. Met Ctrl+T is dat snel opgelost.

Als 'state' gebruik je een String object, Ew! :(
Een nadeel is bijvoorbeeld, dat als je een keer "accellerate" typt (met een 'l' teveel), dan je programma dan niet meer werkt. Met een 'state' als integer en paar "#define" of met een "enum" is dat probleem er niet, dan geeft de compiler een foutmelding bij een typefout.

Normaal gesproken kun je met een state machine ook aangeven als er niets gebeurt. Dus de state "run" kun je dan er ook inzetten. Nu ga je buiten de state machine om tijdens het inlezen van sensors alsnog de state wijzigen. Daarmee breek je de state machine :shock:

Een state machine met de 'state' als integer gaat goed samen met een switch-case statement:
Code: Alles selecteren
  switch( state)
  {
    case RUST:
      state = PAK_GLAS;
      break;
    case PAK_GLAS:
      PakGlas();
      state = VUL_MET_BIER;
      break;
    case VUL_MET_BIER:
      VulMetBier();
      state = DRINK;
      break;
    case DRINK:
      Drink();
      state = RUST;
      break;
    default:
      // program error
      break;
  }

Als je zo iets hebt, dan kun ook gemakkelijk tussen de verschillende states schakelen. Bijvoorbeeld als er geen glazen meer zijn, dan naar de state RUST gaan is eenvoudig toe te voegen.

Je hebt bytes gebruikt voor de pin nummers. Dat soort optimalisaties is misschien handig voor een ATtiny of een interrupt routine, maar niet voor een Arduino Uno. Sommigen vinden dat nogal belangrijk, maar daar gewoon niet naar luisteren :lol: Je kunt 'int' gebruiken, en de compiler laten uitzoeken wat die er mee doet.
Weet je hoeveel byte winst je hebt ? Helemaal niets. De compiler is best wel slim, en de compiler maakt er niet eens variabelen van.

Jouw sketch: Arduino.cc IDE 1.6.12, voor Arduino Uno : 4520 bytes code, 265 bytes ram.
Jouw sketch met 7 keer 'int' voor de const pin nummers : 4520 bytes code, 265 bytes ram

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: train control project

Berichtdoor Koepel » 27 Sep 2016, 08:54

Dokter, ik heb mijn state machine gebroken, is dat erg ?
-Eenmaal per dag.
Huh, wat bedoelt u ?
- Ik zal u arduinoforum.nl voorschrijven.
Okay, ik begrijp het, dankuwel dokter.
-Laat me eens kijken.
Dokter, is uw state machine wel in orde ?

Berichten: 4067
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: train control project

Berichtdoor shooter » 27 Sep 2016, 13:18

jij bent lekker
er staat pak een glas en dan break (het glas)
paul deelen
shooter@home.nl

Gebruikers-avatar
Berichten: 31
Geregistreerd: 08 Sep 2016, 21:50

Re: train control project

Berichtdoor Kitemasters » 28 Sep 2016, 01:50

eerst even toegeven dat veel geleend heb uit een "Blink without delay" voorbeeld.
zeg maar een hoog jat gehalte. :oops:

de acceleration is nu lineair. Het zou natuurlijker overkomen als er een curve in zou zitten.
in het begin zie je langzaam de lampjes aangaan en dan loopt de snelheid recht omhoog.
je zou hoger willen beginnen zodat de lampjes branden en de trein nog net niet rijdt.
daarna de lage snelheid wat langzamer opbouwen terwijl het bij de hoge snelheid sneller mag.

aan de andere kant wiskunde is niet mijn ding, en het loopt best wel lekker nu dus ik weet
niet of ik hier al aan wil beginnen. ook wilde ik er een gui aan koppelen zodat je elk moment kan stoppen,
starten en de max speed kan aanpassen. maar ik heb al wat zitten googlen en zag dat dat ook niet even
simpel is :o

ik kreeg veel reacties dat een string gebruiken wel uit den boze is vanwege geheugen gebruik.
daardoor ben ik byte gaan gebruiken omdat speed en pin nummers nooit meer dan 255 zullen zijn.
maar als het verder niks uitmaakt kan ik daar wel weer int gaan gebruiken.

String object, Ew! :(

dat bedoel ik :) de meesten worden kennelijk niet blij van een string.
ik had nog gezocht naar "ENUM" maar kon er zo snel geen goed voorbeeld vinden over de syntax en het
gebruik ervan.

Een state machine met de 'state' als integer gaat goed samen met een switch-case statement

dank voor je input en dit voorbeeld, hier moet ik even een paar dagen mee sleutelen zeg maar. ;)

als het geheel redelijk af is wilde ik het hele projectje wel op github of arduino ofzo posten.
met filmpje en foto`s. en ik gebruik een sainsmart mega.

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: train control project

Berichtdoor nicoverduin » 28 Sep 2016, 07:20

String heeft het nadeel dat het leidt tot fragmentatie van jouw RAM geheugen. Beetje net als een PC met de harde schijf. Elke keer als je er een letter bij plakt, maakt hij een nieuwe String aan. Het oude stukje blijft gewoon behouden maar zit tussen de andere variabelen en is niet meer aaneengesloten aan het algemene stuk vrije RAM geheugen. Als je dan veel gebruik maakt van String krijg je allemaal van die kleine stukjes die beschikbaar zijn. Is dat erg? hoeft niet tot dat je een keer een stuk groter nodig hebt die niet beschikbaar is. En dit terwijl de som van al die kleine stukjes groot genoeg is.
Grotere machines (PC's, Midrange en mainframes, linux machines ed) hebben een apart stuk software draaien dat al die vrije stukken weer tot een maakt. Dit noemen ze 'garbage collection'. Op de kleine microcontrollers heb je dat niet. En dus gaat het een keer mis.
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: train control project

Berichtdoor Koepel » 28 Sep 2016, 08:48

Je kunt beginnen met #define en een integer "state", en dat kun je later omzetten naar zo'n 'enum'. Het is namelijk hetzelfde.

Ik maak graag een 'IDLE' state, dat is de begin toestand als de Arduino aangezet wordt, of wanneer er niets gebeurt. Soms wordt die niet eens gebruikt.
Code: Alles selecteren
#define STATE_IDLE 0
#define STATE_START 1
#define STATE_ACCELERATE 2
#define STATE_DECELERATE 3
#define STATE_RUN 4

int state = STATE_IDLE;

En dat samen met de switch-case statement.

Er zijn meerdere mogelijkheden om de states te beschrijven. Je zou aparte states kunnen maken voor naar links en naar rechts.

Nu ik er over nadenk, zou ik inderdaad aparte states maken voor naar links en naar rechts. Het zijn namelijk twee verschillende dingen, en misschien wil je vooruit harder rijden dan achteruit. Ik zie 'accelerate' en 'decelerate' niet zozeer als een 'state', maar meer als een uitvoering die nodig is bij een bepaalde 'state'. De state is bijvoorbeeld dat de trein rijdt en nog niet gedetecteerd is, een andere state is dat het wel gedetecteerd is, en weer een andere state is wanneer de trein is gestopt en terug rijdt. Dus dan wordt het: "IDLE", "RUN_RIGHT", "RUN_RIGHT_DETECTED", "RUN_LEFT", "RUN_LEFT_DETECTED". En dan met een aparte variabele voor de snelheid. Je kunt de states ook kiezen aan de hand van de drie stukken rail (tussen de poortjes, links van het linker poortje, rechts van het rechter poortje). Maar dat zijn mijn gedachten. Kies iets wat je zelf begrijpt.

@shooter, dat was super grappig, als je het leest als een soort pseudo-code dan lijkt er iets anders te staan :lol: :lol: :lol:

Gebruikers-avatar
Berichten: 31
Geregistreerd: 08 Sep 2016, 21:50

Re: train control project

Berichtdoor Kitemasters » 28 Sep 2016, 15:33

vraagje tussendoor.....

cpp code
pinMode(motor_Pin, OUTPUT);                    // set motor_Pin as output
pinMode(brake_Pin, OUTPUT); // set brake_Pin as output
pinMode(direction_Pin, OUTPUT); // set direction_Pin as output

// pinMode(sensL, INPUT); // not needed cousse analogread is always input?
// pinMode(sensR, INPUT); // not needed cousse analogread is always input?


klopt dit? of is het beter de pin toch als "INPUT" te zetten.

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: train control project

Berichtdoor nicoverduin » 28 Sep 2016, 18:02

Hoeft niet mag wel. Voor de duidelijkheid is het eigenlijk beter. Dan weet je het zeker.
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

VorigeVolgende

Terug naar Gezamenlijke projecten

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 30 gasten