modeltrein besturing

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

Re: modeltrein besturing

Berichtdoor Koepel » 06 Nov 2016, 22:41

Huh ? :? Kun je nog eens uitleggen wat je wilt ?
Een softwarematige timer met millis() heeft een interval, bijvoorbeeld iedere 3 seconden.
Een vertraging kan ook met millis(), bijvoorbeeld over 10 seconden iets doen.

Een inschakelvertraging en uitschakelvertraging kan ook. Maar dan is het belangrijk om de condities te beschrijven. Wat als de ene nog bezig is terwijl de andere aktief wordt.

Advertisement

Berichten: 37
Geregistreerd: 07 Okt 2016, 10:33

Re: modeltrein besturing

Berichtdoor maartentukker » 07 Nov 2016, 20:09

Ik wil dus alleen de delay's in het huidige programma vervangen door millis(). Om de servo de tijd te geven te activeren en zijn sweep te doorlopen. Dit met dus 2 verschillende tijden. Ik snap alleen niet hoe ik zo'n pauze in dit programma verwerk en deze dus op die momenten kan laten beginnen en eindigen.
Een boolean geeft toch alleen een high of low?

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

Re: modeltrein besturing

Berichtdoor Koepel » 07 Nov 2016, 21:41

Zal ik dan deze sketch nemen ? http://arduinoforum.nl/viewtopic.php?f=9&t=2038#p14986

Waarom is die detach() eigenlijk nodig ? Voor zover ik weet zijn er maar weinig servo motors die dan in standby gaan.

Om een seconde later de detach() te doen, en de leds anders te zetten, dat zou kunnen met één vertraging en één previousMillis.
Wil je ook die 15ms omzetten naar millis() ?
Dat wordt het al snel een state machine of een tabel uitvoeren.
Is de 15ms echt nodig ? Ik kan me niet voorstellen waarvoor :? Het servo signaal maakt dat de servo motor toch wel naar de juiste positie gaat.

Met een functie, zoals shooter schreef, lijkt me ook beter.
De condities goed beschrijven is erg belangrijk. Dus wat gebeurt er als op het verkeerde moment de verkeerde knop wordt ingedrukt ?
Als de nieuwe knop de oude 'override', dan kan ik inderdaad iets maken met één vertraging en één previousMillis.

Eerst maar even de eenvoudigste oplossing, waarbij de loop() toch nog redelijk snel gaat, voldoende om knoppen en sensors in de gaten te houden.
Hier de twee functies die shooter bedoelde:
Code: Alles selecteren
void ServoGoTo( int pin, int value)
{   
  myservo.attach( pin);       // attaches the servo on pin 9 to the servo object
  delay(15); 
  myservo.write( value);                 // sets the servo position according to the scaled value
}

void ServoIdle()
{
  myservo.detach();                    //de-energizes servo
  digitalWrite(straightled, HIGH);   //indication led turnover straight pos
  digitalWrite(turnled, LOW);
}


Dan de globale variabelen.
Code: Alles selecteren
unsigned long previousMillis;
boolean servoDelayActive = false;

const unsigned long delaydetach = 1000;   // mag ook een 'int' zijn.


Dan de vertraging starten met de knoppen.
Code: Alles selecteren
  // if button is pressed, turnover switches to straight
  if (openButtonState == LOW) {
    ServoGoTo( 9, 100);
    previousMillis = millis();      // timestamp this moment
    servoDelayActive = true;    // enable the delay   
  }

Voor de andere knop hetzelfde, alleen de positie van 100 is dan 80.

Vervolgens ergens onderaan de loop() kijken of het al tijd is om de servo idle te maken.
Code: Alles selecteren
void loop() {
  unsigned long currentMillis = millis();         // just one currentMillis for the whole loop()

  ...
  ...
  ...

  // Check if the delay is active and the time has finished.
  if( servoDelayActive)
  {
    if( currentMillis - previousMillis >= delaydetach)
    {
      ServoIdle();
      servoDelayActive = false;        // disable this delay, we don't need it after this.
    }
  }
}


Begrijp je de bedoeling ? Het moment waarop de vertraging begint, maak je een 'timestamp' van de tijd door millis() van dat moment te onthouden. Daarna kijken of de tijd al verlopen is. Maar wel met een variabele die aangeeft of de vertraging op dat moment actief is.

Alles is dus eenmalig. Daarom hoeft de 'previousMillis' niet opgehoogd te worden. Als de vertraging over is en ServoIdle() is uitgevoerd, dan is het klaar. Wat de waarde van 'previousMillis' dan is, dat maakt niet uit, want de 'servoDelayActive' heeft de vertraging disabled.

Berichten: 37
Geregistreerd: 07 Okt 2016, 10:33

Re: modeltrein besturing

Berichtdoor maartentukker » 07 Nov 2016, 21:53

Elke keer als ik de arduino opnieuw aan zet gaan de settings naar default, zoals aangegeven in de setup.
Is het mogelijk om de laatste servo, LED, relais standen te onthouden en deze bij opnieuw aanzetten meteen in de juiste positie te laten en weer te geven (led) waar nodig?
Nu gaan bv bij de servo programmering tbv de wissels de led's niet aan, tot ik op een knop druk en dus de servo naar die stand gaat en daarmee de desbetreffende led ook gaat branden. Daarvoor blijft de servo dan ook tsjitteren omdat deze nog geen detach opdracht gehad heeft.

Het zou mooi zijn als ik de stroom aan zet voor de treinbesturing, ik niet eerst alle wissels handmatig moet aansturen en daarmee een begin positie krijg. Dit geldt dan natuurlijk ook voor de trein detektie met reed modules, mits de trein recht boven een reed staat.

Berichten: 37
Geregistreerd: 07 Okt 2016, 10:33

Re: modeltrein besturing

Berichtdoor maartentukker » 07 Nov 2016, 22:01

Die uitleg over millis, maakt alles een stuk duidelijker :D . Bedankt! Ik ga het straks aanpassen en proberen!!

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

Re: modeltrein besturing

Berichtdoor Koepel » 07 Nov 2016, 23:53

Je kunt het in EEPROM opslaan.
Bijvoorbeeld bij een Arduino Uno kun je de interne EEPROM 100000 (100k) keer schrijven voordat een geheugentje van het EEPROM stuk is.
Bij de nieuwere processoren is er geen interne EEPROM. De externe EEPROMs zijn goedkoop, 32kbyte voor 50 cent.

Code: Alles selecteren
void ServoGoTo( int pin, int value)
{   
  myservo.attach( pin);       // attaches the servo on pin 9 to the servo object
  delay(15);
  myservo.write( value);                 // sets the servo position according to the scaled value
  EEPROM.write( 0, (byte) value);   // store last value of servo in eeprom location 0
}


Code: Alles selecteren
void setup() {
  int lastServoValue = EEPROM.read( 0);       // read byte from location 0
  ...


Er zijn verschillende manier om het EEPROM te gebruiken : https://www.arduino.cc/en/Reference/EEPROM
Wat gebeurt er als de stroom van de Arduino uit viel, terwijl die naar EEPROM aan het schrijven was ?
Daarom schrijf ik op hoe het EEPROM is ingedeeld, en ik voeg daar een checksum aan toe.
Je kunt een 'struct' maken met allerlei variabelen, en die via een EEPROM.update() schrijven, dan wordt de waarden die niet wijzigen ook niet opnieuw geschreven.

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

Re: modeltrein besturing

Berichtdoor shooter » 08 Nov 2016, 21:04

eeprom alleen doen als de spanning minder wordtm dus een simpele elco is eigelijk al genoeg.
als spanning wegvalt heb je toch een probleem, want alle servos bewegen als je de voeding aansluit
en als er een as op de wissel staat gaat deze eraf.
denk ook aan een tegenveer voor het openrijden.
paul deelen
shooter@home.nl

Berichten: 37
Geregistreerd: 07 Okt 2016, 10:33

Re: modeltrein besturing

Berichtdoor maartentukker » 11 Nov 2016, 20:26

Ik heb de code herschreven volgens onderstaand concept, maar ik krijg steeds de volgende foutmelding:

ldr_en_servo_combinatie_millis_2.ino:113:1: error: expected declaration before '}' token
Fout bij compileren.

Maar ik kom er maar niet achter waar het hem in zit, ik heb al van alles geprobeerd, hebben jullie enig idee?
cpp code
// LDR data

// set pin numbers:
const int LDRPin[] = {2,3}; // the number of the LDR pins
const int ledPin1 = 4; // the number of ledPin block in
const int ledPin2 = 5; // the number of ledPin block out

// variables will change:
int LDRState = 1; // variable for reading the LDR status


// __________________________________________________________
// servo data

#include <Servo.h>

Servo myservo; // create servo object to control a servo

// constants
int openButtonPin = 10;
int closeButtonPin = 11;
int servoPin = 9;
int straightled = 6;
int turnled = 7;

// millis for servo instead of delay
unsigned long previousMillis;
boolean servoDelayActive = false;

const unsigned long delaydetach = 1000; // mag ook een int zijn


//variables
int servoPos = 80; // the current server position. Change it to whatever position you want your claw to start out at.
int openButtonState = 0;
int closeButtonState = 0;



void setup() {

Serial.begin(9600);
Serial.print("ldr en servo combinatie millis");

// LDR setup

// initialize the LED pin as an output:
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
// initialize the pushbutton pin as an input:
for(int x=0; x<2; x++)
{
pinMode(LDRPin[x], INPUT);
}

// servo setup

// setup the input pins on the Arduino
pinMode(openButtonPin, INPUT);
pinMode(closeButtonPin, INPUT);

pinMode(straightled, OUTPUT);
pinMode(turnled, OUTPUT);


// create the servo object
myservo.attach(servoPin); // attaches the servo to the servo object
myservo.write(servoPos);

}

void loop(){

unsigned long currentMillis = millis(); // just one currentMillis for the whole loop ()

// read the state of the LDR value one by one (2 in total in this case):
for(int x=0; x<2; x++)
{
LDRState = digitalRead(LDRPin[x]);

// check if the LDR is activated.
// if it is, the LDRState is LOW.
if (LDRState == LOW && LDRPin[x] == 2) { // x == 2 means the first LDR in line at begin of block
// turn occupation LED on:
digitalWrite(ledPin1, HIGH);
digitalWrite(ledPin2, LOW);
}
if (LDRState == LOW && LDRPin[x] == 3) { // x == 3 means the second LDR (at pin 3) in line at the end of block
// turn block free LED on:
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, HIGH);
}
}

// servo loop

// read the state of the buttons
openButtonState = digitalRead(openButtonPin);
closeButtonState = digitalRead(closeButtonPin);

}
void ServoGoTo (int pin, int value)
{
myservo.attach(pin); // attaches the servo control on pin 9 to the servo object
delay (15);
myservo.write(value); // sets the servo position according to the scaled value
}

void ServoIdle ()
{
myservo.detach(); //de-energizes servo control
}
}
}
if (openButtonState == LOW) { //if button is pressed turnover switches to bend

ServoGoTo (9, 100);
previousMillis = millis(); // timestamp at this moment
servoDelayActive = true; // enable the delay
digitalWrite (straightled, LOW);
digitalWrite (turnled, HIGH);

}
if (closeButtonstate == LOW) {

ServoGoTo (9, 80);
previousMillis = millis();
servoDelayActive = true;
digitalWrite (straightled, HIGH);
digitalWrite (turnled, LOW);

}

// Check if the delay is active and the time has finished.
if (servoDelayActive) {
if (currentMillis - previousMillis >= delaydetach) {
ServIdle();
servoDelayActive = false; // disable this delay, we don't need it after this
}
}

// print the servo position to the serial console
Serial.println(servoPos);
}

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

Re: modeltrein besturing

Berichtdoor Koepel » 11 Nov 2016, 20:52

De compiler zegt dat je bij regel 113 een rommeltje van de haakjes hebt gemaakt.
Druk op Ctrl+T en zorg dat code in een functie ook code in een functie is, en dat een functie ook een functie is.

De setup() en loop() zijn functies. Als je zelf een functie maakt, dan staat die op hetzelfde niveau als setup() en loop(). Dus niet binnen een andere functie.

Code: Alles selecteren
void setup()
{
  ...
}

void loop()
{
  ...
  myFirstFunction( 112);   // aanroep
  ...
}

void myFirstFunction( int level)    // definitie van de functie
{
  ...
}

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

Re: modeltrein besturing

Berichtdoor shooter » 12 Nov 2016, 23:35

bij sommige moeten de functies eerst en dan pas de setup en loop.
paul deelen
shooter@home.nl

VorigeVolgende

Terug naar C code

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 35 gasten