Modelbaanbesturing > Elektronische en digitale techniek

Analoog rijden met geluid - het project.

(1/46) > >>

Rob:
Na alle experimenten met geluid aan boord is het tijd geworden een draadje te starten over het project

Analoog rijden met geluid


Het prototype van de geluid (en licht) module is in de railbus ingebouwd en werkt tot nu toe naar behoren. Hier een filmpje over het prototype en de introductie van het project.



Het geheel bestaat uit 2 onderdelen:

* De pulsbreedte besturing.
Deze is opgebouwd rond een Arduino met motorcontroller. Ik ben bezig een versie met een draaiknop (potmeter) in elkaar te zetten. Een bedradingsschema, de Arduino schets (programma) en bouwbeschrijving komt binnenkort.

* De geluid/licht module aan boord. Deze bestaat uit een Arduino en MP3 speler (DFplayer)
Ook hiervan komt t.z.t. een gedetailleerde beschrijving. Maar naast de hardware en software bestaat een flink deel van het werk uit het vinden en bewerken van de juiste geluidsfragmenten.

De belangrijkste reden om dit project te starten, en niet over te stappen op bijvoorbeeld een digitaal systeem, is de bestaande analoge verzameling aan locs en treinstellen. Met deze opstelling kunnen alle locs, met of zonder geluidsmodule, op hetzelfde systeem blijven rijden. Ombouw kan dus geleidelijk en tegen relatief lage kosten. Daarnaast vind ik het gewoon leuk een met elektronica, programmeren en geluidsbewerking te stoeien.

Alvast even een indicatie van de kosten. Deze worden sterk bepaald waar je spullen besteld (dichtbij is wat duurder, maar veel sneller dan spullen van tante Ali):
- pulsbreedtebesturing: 15 - 25 euro (relatief duur zijn de knopjes voor de 6 functietoetsen)
- geluidsmodule 10 - 20 euro per stuk
Bij de bouwbeschrijving komt een lijst met benodigde onderdelen en dan kunnen ook de kosten wat nauwkeuriger worden aangegeven.

Zoals in het introductiefilmpje al is aangekondigd, wordt de volgende geluidsmodule in een stoomtrein, de BR50, ingebouwd. Ik heb nog niet alle spullen uit China, maar ondertussen ben ik wel alvast begonnen met het zoeken naar de ruimte voor de componenten van de geluidsmodule in deze loc.



De opbouw van de geluidsmodule is afhankelijk van waar de spullen passen. De voeding op de Arduino is in ieder geval al iets compacter geworden dan het prototype ....

Volgende stap: de bouwbeschrijving van de pulsbreedtebesturing met draaiknop...

Rob

Pierre:
Ik blijf je vol spanning volgen en wachten op de schema's Rob. Mijn interesse is zeer zeker gewekt door je voor dit project. Top man! ;)

Rob:
Dank je, Pierre.
Voor het eerste deel zal ik je niet heel veel langer in spanning laten. Ik ben aardig aan het friemelen geweest om het experimentele gebeuren, dat vooral met proberen tot stand gekomen, om te zetten naar iets reproduceerbaars. Dat is ondertussen gelukt (onder meer door de draadjes van het probeer-spoor vast te solderen!). Aansluitschema, code en filmpje volgt snel.
Rob

Rob:
De pulsbreedte besturing
Met pulsbreedte besturing kan analoog worden gereden en zijn er mogelijkheden voor geluid aan boord van de treinen. Ook zonder geluid is deze besturing te gebruiken voor analoge treinen. Het voordeel is dat (langzaam) rijden beter gaat.

In dit bericht een filmpje over de bediening van de pulsbreedtebesturing, het aansluitschema, de code voor de Arduino, een stuklijst en wat aanwijzingen voor de opbouw.

Bediening

Hoe het een en ander in de praktijk werkt, is te zien in dit filmpje.



Aansluitschema

Voeding, motorcontroller, Arduino en de bediening wordt als volgt aangesloten.




De ingang van de besturing neemt elke gelijk of wisselspanning tussen 5 en 35 V, dus ook een conventionele treintrafo voldoet. Belangrijk is dat de trafo niet te sterk is; het is de bedoeling dat de spanning 'dipt' als er kortsluiting op de baan ontstaat. Een trafo van rond de 35 Watt (VA) is prima.
De gelijkrichter zorgt er voor dat de ingangstroom altijd goed op de step up/down print komt. Deze is ingeregeld op een uitgangsspanning van 11,5 V. Let op: Deze spanning moet worden ingeregeld voor de rest wordt aangesloten (bij mij was de uitgang 20V af fabriek, en dat is meer dan de Arduino aan kan).
De voeding levert stroom aan de motorcontroller (en daarmee ook aan de trein) en aan de V-IN van de Arduino. De Arduino heeft een ingebouwde uitgang voor een gestabiliseerde 5V, waarmee de potmeter als 'spanningsdeler' naar de massa wordt aangesloten.
De stand van de potmeter wordt uitgelezen op de analoge ingang A7. Deze wordt omgerekend naar een puls voor de rijstroom op 'analoge' uitgangen D09 en D10 van de Arduino. Deze zijn verbonden met de aansturing van de motorcontroller (een pin voor elke richting).
Verder zijn 6 druktoetsen op pinnen A0-A5 verbonden met de massa, dit zijn de functietoetsen voor de geluidsmodule. Een LED op pin D13 geeft informatie over de rijstroom. Dit is dezelfde pin als de op de Arduino ingebouwde LED, dus eventueel kan van deze LED worden afgezien.


Programmacode (sketch)

De code voor de Arduino:

--- Code: ---/* PULSBREEDTEBESTURING VOOR MODELTREIN
 * versie 2.0 - mei 2018
 * Rob van Deursen
 *
 * Motor snelheids regeling met potmeter of Infrarood (IR) afstandsbediening.
 * Ook geschikt voor "analoge" geluidsmodules middels 6 functietoetsen.
 *
 * ==> Kies hier welke besturing wordt gebruikt: <==
*/
const bool IRbesturing = false;   // zet deze waarde op true als IR ontvanger wordt gebruikt
                                  // bij false is de besturing met een potmeter en functietoetsen

/*
 * De motorbesturing gebeurt over 2 'analoge' uitvoer pinnen. Hier wordt met pulsbreedte modulatie
 * de (effectieve) uitgangsspanning ingesteld.
 * Elke rij-richting heeft 1 pin waarmee de pulsbreedte tussen 0 (uit) en 255 (maximaal) wordt geregeld.
 *   
 * Potmeter bediening
 * ------------------
 * De potmeter bestuurt de rijstroom volgens het het principe: "draai naar rechts, rij naar rechts".
 * Vanuit de middenpositie kan de snelheid daarmee in 2 richtingen worden geregeld.
 *
 * Bij starten van de Arduino moet de potmeter in de nul stand staan. Zo wordt bij een reset na kortsluiting
 * voorkomen dat er meteen weer spanning op de uitgang komt te staan. De indicator led knippert snel als
 * de potmeter niet op nul staat. De potmeter kan dan alsnog in het midden worden gesteld, waarna de bediening
 * start.
 *
 * Indicaties van de LED:
 *    - continue brandend: potmeter staat in "stop" bereik. Er is geen rijstroom.
 *    - langzaam knipperend: potmeter staat in "geluidsfunctie" bereik. Er is enige rijstroom om de geluidsmodule
 *      te starten, maar niet genoeg om de motor te laten draaien.
 *    - uit: gewone rijstroom in een van de rijrichtingen.
 *    - snel knipperend: potmeter moet eerst naar 0 (midden) worden gedraaid. Geen rijstroom.
 *   
 * Functietoetsen:
 * Er zijn tot 6 functietoetsen aan te sluiten. Elke toets verandert kort de frequentie van de rijstroom.
 * Deze frequentie-veranderingen worden door een geluidsmodule herkent en start daarmee speciale functies.
 *
 * 
 * IR afstandsbediening
 * --------------------
 * Infrarood afstandbedieningen kunnen ook worden gebruikt voor deze pulsbreedtebesturing.
 * Deze werkt als volgt:
 * Een InfraRood ontvanger vangt de signalen van de afstandsbediening op.
 * Deze wordt gedecodeerd en omgezet naar een rijrichting en snelheid.
 * Snelheid wordt geleidelijk geregeld. Elk commando levert een 'gewenste' snelheid
 * en rijrichting op. Vervolgens wordt langzaam geaccelereerd of gedecelereerd.
 * Rijrichting wisselt alleen als de snelheid 0 is.
 *
 * Indicaties met 3 leds:
 * 2 richting leds: geven draai-of rijrichting aan.
 *   - continue brandend: rijrichting is ingesteld en snelheid is de gewenste snelheid
 *   - knipperen: andere gewenste snelheid en/of rijrichting. Verandering is bezig
 * 1 'stop' led:
 *   - continue brandend: motor staat stil (snelheid = 0}
 *   - knipperend: er wordt afgeremd tot stop {gewenste snelheid = 0)
 *   - uit: motor draait / rijdt
 *   
 * Voor het ontvangen van het IR signaal is gebruik gemaakt van de IRremote bibliotheek
 * Elke IR afstandbediening kan worden gebruikt, daarvoer moeten de overeenkomstige codes in
 * dit programma worden gezet. De decosering wordt gedaan in de functie "VertaalIR()".
 * Er is standaard voorzien in het gebruik van de Keyes afstandsbediening, maar deze heeft geen
 * functietoetsen voor eventuele geluidsmodules.
 */


// ------------ Instellingen per invoer apparaat ----------

// === potmeter besturing ===

// gebruiksinstellingen
#define potmeterRuis      3    // drempelwaarde voor ruis op de potmeter, voorkomt 'jutteren'
#define potmeterMidden  512    // middenstand (= 0 stand) van de potmeter. Normaal ligt de waarde tussen 0 en 1023.
#define nulbereik        60    // bereik van de potmeter buiten het midden waarop de rijstroom 0 blijft
#define geluidbereik    120    // bereik van af de nul-grens waarop de rijstroom op de minimale waarde blijft voor de geluidsmodule
#define maximaalbereik  500    // bereik waarop de maximale waarde wordt bereikt

// pin definities
#define potmeter         A7    //potmeter (snelheidsregelaar) pin
#define functietoets1    A0    // functietoetsen 1 t/m 6
#define functietoets2    A1
#define functietoets3    A2
#define functietoets4    A3
#define functietoets5    A4
#define functietoets6    A5
#define ledIndicator     13    // pin voor indicator led (bij gebruik potmeter bediening)

// === IR afstandsbediening ==

// gebruiksinstellingen
#define lusVertraging   30     // delay in ms in de hoofdlus
#define acceleratieStap 0.025  // stappen waarin snelheid toe- of afneemt
#define sprongWaarde    2.5    // snelheids 'sprong', bijvoorbeeld om te koppelen bij rangeren

// pin definities
#define receiver          7    // pin 1 van IR ontvanger naar Arduino digitale pin
#define ledVooruitPin     4    // pinnen voor vooruit/achteruit indicatie (alleen gebruikt bij IR)
#define ledAchteruitPin   2
#define ledStopPin        3    // pin voor stop


// ------------ Instellingen motor controller ----------

// uitvoer pinnen
#define richtingPin1     10    // pinnen voor vooruit en achteruit (dit moeten beide PWM pinnen zijn)
#define richtingPin2      9
#define aanloopPWM      65.0   // Pulsbreedte waarde (0-255) om aanloopweerstand motoren te overwinnen
#define maxPulsBreedte  250    // Maximale pulsbreedte voor de rijstroom (255 of kleiner, met geluid: max 250)


// ------------- Potmeter rijregeling variabelen ------

const int rijbereik = maximaalbereik - geluidbereik;
int potmeterWaarde      = potmeterMidden ;
int vorigePotmeterWaarde= potmeterMidden ;

int functietoets[] {functietoets1, functietoets2, functietoets3, functietoets4, functietoets5, functietoets6};
#define aantalFunctietoetsen 6


// // -------------- Objecten en variabelen t.b.v. IR bediening ------

#include <IRremote.h>
IRrecv irrecv(receiver);       // IR ontvanger object maken
decode_results results;
int IRcode = 0;                // code afgelezen uit IR ontvanger
String IRknop = "";            // de ingedrukte knop (of ingedrukt gehouden)

// regeling van snelheid en richting
int richting = 0;                    // rijrichting
int gewensteRichting = 0;            // gewenste rijrichting (rijrichting schakelt pas om bij snelheid 0)
float snelheid = 0;                  // huidige snelheid
float gewensteSnelheid = 0;          // gewenste snelheid
float acceleratie = acceleratieStap;
float sprong = 0;                    // toename in snelheid bij indrukken 'spring' knop
int richtingPin[] {richtingPin1,richtingPin2}; // pinnen voor vooruit en achteruit (PWM pinnen)


// ------------- Definities en variabelen voor geluidsmodule pulsen -----

#define geluidAan           -.825     // snelheid om geluidsmmodule te starten (kleiner dan 0, snelheid 0 is aanloopPWM motoren)

// rijstroom             ~ 490.0     // gemeten periode (trilligstijd) 2020 us foor standaard PWM rijstroom (~490 Hz)
#define freqFunctie1       667.0     //  667 Hz (periode ~1500 us) ==> 1500
#define freqFunctie2       800.0     //  800 Hz (periode ~1250 us) ==> 1250
#define freqFunctie3      1000.0     // 1000 Hz (periode ~1000 us) ==>  990
#define freqFunctie4      1250.0     // 1250 Hz (periode  ~800 us) ==>  790
#define freqFunctie5      1667.0     // 1667 Hz (periode  ~600 us) ==>  590
#define freqFunctie6      2000.0     // 2000 Hz (periode  ~400 us) ==>  490
#define pulsFunctie         40       // tijdsduur van de puls in ms
#define functiepulsCorrectie 5.0     // correctie voor "handmatige" puls - Arduino tijd 1/4 periode
#define functiePulsIRfactor  0.8     // correctie voor vertraging Arduino door IR

float freqFunctie[] {freqFunctie1, freqFunctie2, freqFunctie3, freqFunctie4, freqFunctie5, freqFunctie6};
#define aantalFreqFuncties    6

int geluidFunctie = 0 ;               // huidige geluid functietoets


// -------------- Overige variabelen ------------------

int t=0;                             // algemene teller voor for... loops
int waardePWM;                       // huidige waarde van de pulsbreedte.
int vorigeWaardePWM;                 // vorige waarde van de pulsbreedte.

// LED indicatoren
unsigned long prevms = 0;            // knipperen laatste keer aan/uit
unsigned long curms = millis();      // knipperen nu
const long blnkint = 250;            // knipper-interval
int ledPins[] {ledVooruitPin, ledAchteruitPin, ledStopPin, ledIndicator} ;
int ledStatus[] {2,0,2,0};             // vooruit (aan), achteruit (uit), stop (aan), indicator (uit).
int blnk = HIGH;


//--------------- Setup na starten Arduino ---------------------

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);     // ingebouwde led op pin 13 uit
  digitalWrite(LED_BUILTIN, LOW); 
 
  // in- en output pinnen initialiseren
  pinMode (richtingPin[0], OUTPUT);
  pinMode (richtingPin[1], OUTPUT);
 
  pinMode (potmeter, INPUT);
  for (t = 0; t < aantalFunctietoetsen; t++) {
    pinMode (functietoets[t],INPUT);
    digitalWrite(functietoets[t],HIGH);
  }

  for (t=0; t<4; t++) {
    pinMode (ledPins[t],OUTPUT);
  } 

  // de gewenste besturing starten
  if (IRbesturing) {                // IR bediening
    irrecv.enableIRIn();            // Start de IR ontvanger
  }
  else {                            // potmeter bediening
    // bij potmeterbesturing moet bij het opstarten snelheid 0 zijn ingesteld
    // bij een reset door kortsliting wordt zo voorkomen dat de rijstroom vanzelf aan gaat
    // led indicator knippert snel zolang potmeter niet op 0 is gesteld
    while (HaalSnelheid(analogRead (potmeter)) != 0) {
      // rijstroom uit bij opstarten
      analogWrite (richtingPin[0], 0);
      analogWrite (richtingPin[1], 0);
      digitalWrite(ledIndicator,digitalRead(ledIndicator) == 0);
      delay(100);
    }
    digitalWrite (ledIndicator,LOW);
  }

}

// --------------- Hoofd lus Arduino ---------------------------

void loop() {
// === IR besturing ===

  if (IRbesturing) {
    sprong = 0;
    if (irrecv.decode(&results)) {
      IRcode = results.value;
      if (IRcode != 0xFFFFFFFF) { // Geen toets herhaling
        IRknop = VertaalIR(IRcode);
      }
      ZetGewensteSnelheidEnRichting (IRknop);
     
      irrecv.resume();            // Doorgaan met IR codes ontvangen
    }
    // snelheid en richting aanpassen
    SnelheidAanpassen() ;
    SnelheidNaarPWM () ;       
    if (snelheid == 0) {          //motor staat stil, dus eventuele richtingverandering doorvoeren
      richting = gewensteRichting ;
    }
    // geluidsmodule bedienen
    if (IRknop.startsWith("-1G0")) {                  // geluid functieknop
      geluidFunctie = VertaalIRfunctie (IRknop);
    }
  }
// === potmeter besturing ===

  else {                                        // geen IR besturing, maar potmeter met functieknoppem
    potmeterWaarde = analogRead (potmeter);
    if (abs(potmeterWaarde - analogRead (potmeter)) < potmeterRuis) {     // stabiele uitlezing
    // verander de snelheid met ruisonderdrukking van de ruis op de potmeter.
      if (abs (potmeterWaarde - vorigePotmeterWaarde) > potmeterRuis) {   // verandering groter dan de ruis
        snelheid = HaalSnelheid (potmeterWaarde);                         
        vorigePotmeterWaarde = potmeterWaarde;
        ledStatus[3] = 2;                         // stop = led continu aan
        if (snelheid == geluidAan) {
          ledStatus[3] = 1;                       // geluid bereik (niet rijden) = lijd knipperen
        } else if (snelheid > 0) {
          ledStatus[3] = 0;                       // rijden = led uit
        }
      }
      richting = (potmeterWaarde < potmeterMidden);
      SnelheidNaarPWM () ;
    }
    // Functietoetsen uitlezen
    geluidFunctie = HaalFunctieToets();
   }
// === voor zowel IR als potmeter ===

  // functie uitvoeren
  if (geluidFunctie > 0) {
    stuurPuls (freqFunctie[geluidFunctie-1],pulsFunctie, true); // stuur een puls voor functie 1-6 op geluidsmodule
    delay(93);                                        // voorkom ongewenste herhaling
    geluidFunctie = 0;                                // functie is uitgevoerd
  }
  // led indicators bijwerken
  ZetLedIndicators();
  for (t=0; t < 4; t++) {
    setLed(t,ledStatus[t]);
  }
 
  delay(lusVertraging);

}
//---------------- Functies --------------------

// === Algemene functies ===

// SNELHEID NAAR PWM OMREKENEN EN OP JUISTE PIN ZETTEN
// naar een pulsbreedte en op de juiste uitvoer pin gezet.
void SnelheidNaarPWM () {
  if (snelheid != 0) {
    waardePWM = aanloopPWM + (maxPulsBreedte-aanloopPWM)/9 * (snelheid + sprong);
  }
  else {
    waardePWM = 0;
  }
  analogWrite(richtingPin[richting == 0],0);      // niet richting pin altijd uit
  if (abs(waardePWM - vorigeWaardePWM) >1) {    // significante verandering PWM
                                                  // voorkom onnodig PWM schrijven: dit verandert de puls
  }
    analogWrite(richtingPin[richting],(waardePWM)); // PWM op richting pin
    vorigeWaardePWM = waardePWM;                  // onthou vorige waarde
  //Serial.print(waardePWM);
}
// ====

// LED AAN, UIT OF KNIPPEREN
// input: led number (0-3)
//        func: 0 = uit, 1=knipper, 2 = aan
void setLed (int led, int func) {
  // knipperstatus bijwerken   
  curms = millis();
  if (curms - prevms >= blnkint) {
    prevms = curms;
    blnk = !blnk;            // wissel blnk status
  }
  // leds uit, aan of knipperstatus
  if (func == 1) {           // dan knipperen
    digitalWrite(ledPins[led], blnk);
  }
 
  if (func == 0) {           // uit
    digitalWrite(ledPins[led], LOW);
  }
  if (func == 2) {           // aan
    digitalWrite(ledPins[led], HIGH);
  }
}
// ====

// STUUR PULS
// zet een signaal puls op de rijstroom met een andere frequentie dan de rijstroom
// Input: frequentie (maximaal 2.000 Hz)
//        tijdsduur van de puls (ms)
//        boolean PWM correctie of niet
void stuurPuls (unsigned int frequentie , unsigned long tijdsduur, boolean PWMcorrectie) {
  unsigned long s;
 
  //golf lengte en -vorm berekenen
  unsigned int kwartGolf = (250000/frequentie) - functiepulsCorrectie;    // lengte kwart cyclus in micro sec, minus Arduino tijd
  if (IRbesturing) {kwartGolf = functiePulsIRfactor * kwartGolf; }
  unsigned int hc = 3* kwartGolf;                       // lengte hoge cyclus, standaard is 3/4 hoog.
  unsigned int lc = kwartGolf;                          // lengte lage cyclus
  if (PWMcorrectie) {                                   // PWM correctie gevraagd
    if (waardePWM < 90) {                               // grove PWM correctie in 1/4, 1/2 of 3/4 pulsbreedte (3/4 is standaard)
      hc = kwartGolf;
      lc = 3 * kwartGolf;
    } else if (waardePWM < 170) {
      hc = 2 * kwartGolf;
      lc = 2 * kwartGolf;
    }
  }
 
  //puls op de rijstroom pin zetten
  s = millis() + tijdsduur;
  while (millis() < s) {
    digitalWrite(richtingPin[richting],HIGH);
    delayMicroseconds (hc);
    digitalWrite(richtingPin[richting],LOW);
    delayMicroseconds (lc);
  }
  analogWrite(richtingPin[richting],(waardePWM));
}

// ===

// === potmeter bediening functies ===

// POTMETER WAARDE OMREKENEN NAAR SNELHEID
// input: AD waarde potmeter

float HaalSnelheid (int ADwaarde) {    // snelheid instellen op basis van de potmeter
  float s = abs (ADwaarde - potmeterMidden);
  if (s < nulbereik) {
    s = 0;
  }
  else {
    if ( s < geluidbereik ){
      s = geluidAan;
      //Serial.println("!!!!");
    }
    else {
      s = (constrain (s, geluidbereik, maximaalbereik) ) - geluidbereik;
      s = 10 * s / maximaalbereik;
    }
  }
 
  return s;
}
//===

// FUNCTIETOETSEN UITLEZEN
// geeft het volgnummer van de ingedrukte functietoets.
// 0 = geen toets
int HaalFunctieToets () {
  int  f = 0;                        // toets volgnnummer
  int  k = 0;                        // ingedrukte toets (0 = geen)
  for (f=0; f < aantalFunctietoetsen; f++) {
    if (digitalRead(functietoets[f]) == LOW) {  //Deze toets is ingedrukt
      k = f+1;                       // onthou toets volgnummer
      //Serial.print(k);
    }
  }
 
  if (k > 0) { delay (60);}
  return k;
}
// ===

// === IR bediening functies ===

// IR CODE VERTALING
// Vertaling van de IR codes naar knoppen c.q. acties
// input: integer met de ontvangen IR code
// output: string met code of actie
//         Numerieke toetsen geven het cijfer als string terug.
//         Alle niet-numerieke toetsen beginnen met "-1", zodat
//         deze makkelijk zijn te onderscheiden van de numerieke toetsen.

String VertaalIR(int code){       

  String b = "";
 
  switch(code) {
    // code vertaling KEYES afstandsbediening
    case 0xFFA25D: b="1"; break;     //numerieke toets is snelheid 0-9
    case 0xFF629D: b="2"; break;
    case 0xFFE21D: b="3"; break;
    case 0xFF22DD: b="4"; break;
    case 0xFF02FD: b="5"; break;
    case 0xFFC23D: b="6"; break;
    case 0xFFE01F: b="7"; break;
    case 0xFFA857: b="8"; break;
    case 0xFF906F: b="9"; break;
    case 0xFF9867: b="0"; break;
    case 0xFF6897: b="-1*"; break;    //* = sprong knop snelheidssprong (t.b.v. koppelen bij rangeren, bijvoorbeeld)
    case 0xFFB04F: b="-1#"; break;    //# = direct naar gewenste snelheid (geen acceleratie/deceleratie)
    case 0xFF18E7: b="-1^"; break;    //omhoog
    case 0xFF10EF: b="-1<"; break;    //links
    case 0xFF38C7: b="-1STOP"; break; //OK = noodstop
    case 0xFF5AA5: b="-1>"; break;    //rechts
    case 0xFF4AB5: b="-1V"; break;    //omlaag
    case 0xFFFFFFFF: b="-1R"; break;  //herhaal (repeat) laatste knop blijft ingedrukt

    // code vertaling SHARP GA074WJSA afstandbediening
    case 0x885B30D5: b="1"; break;
    case 0xE7E0CFB1: b="2"; break;
    case 0xA34F5A01: b="3"; break;
    case 0x22614D75: b="4"; break;
    case 0x96C5A8AB: b="5"; break;
    case 0x44ABD1FD: b="6"; break;
    case 0x1A5C4D:   b="7"; break;
    case 0x57A67691: b="8"; break;
    case 0x9543D7CF: b="9"; break;
    case 0xF4C976AB: b="0"; break;
    case 0x5CC96CE7: b="-1*"; break;    //kanaal wissel = sprong knop snelheidssprong (t.b.v. koppelen bij rangeren, bijvoorbeeld)
    case 0xCC00A5B7: b="-1#"; break;    //TV/VIDEO = direct naar gewenste snelheid (geen acceleratie/deceleratie)
    case 0x3E0C7005: b="-1^"; break;    //omhoog
    case 0xB10C7C8B: b="-1^"; break;    //channel up = ook omhoog
    case 0x503D6F71: b="-1V"; break;    //omlaag
    case 0x10921B67: b="-1V"; break;    //channel down = ook omlaag
    case 0x25D2E369: b="-1STOP"; break; //OK = noodstop
    case 0x6D5D1DB3: b="-1STOP"; break; //AAN/UIT = ook noodstop
    case 0xF43135:   b="-1>"; break;    //rechts
    case 0x4B12992B: b="-1>"; break;    //volume + = ook rechts
    case 0xA574865B: b="-1<"; break;    //links
    case 0x1BE8C80D: b="-1<"; break;    //volume - = ook links

// functietoetsen geluidsmodule
    case 0x47071827: b="-1G01" ; break;    //rood  = F1
    case 0xAA849FD1: b="-1G02" ; break;    //groen = F2
    case 0xA0A3EAD:  b="-1G03" ; break;    //geel  = F3
    case 0xC578C8FD: b="-1G04" ; break;    //blauw = F4
    case 0xAE90AC1D: b="-1G05";  break;    //sound = F5
    case 0xC7E0BECF: b="-1G06" ; break;    //menu  = F6
    case 0x28CBA803: b="-1G04" ; break;    //mute  = F4
     
    case 0x3FE6:     b="-1G<"  ; break;    //subtitle = minimalw PWM links
    case 0xA07CF2DB: b="-1G>"  ; break;    //end      = minimale PWM rechts

  //  case 0xFFFFFFFF: b="-1R"; break;  //herhaal (repeat) laatste knop blijft ingedrukt

 
    // Hier is ruimte om eventueel codes van andere afstandbedieningen te vertalen
 
  default:
    b = "-2Onbekend";
  }// End Case
 
  return b ;
}
// ====

// SNELHEID AANPASSEN - IR
// Deze functie berekent de nieuwe snelheid op basis van de
// ingestelde acceleratie.


void SnelheidAanpassen() {
  if (abs(snelheid - gewensteSnelheid) <= (acceleratieStap / 2)) {
    snelheid = gewensteSnelheid;
    acceleratie= 0;
  } else {
    snelheid += acceleratie;
  }
}
// ===


// ZET DE GEWENSTE SNELHEID EN RICHTING -IR
// Functie zet de gewenste snelheid, gewenste richting en gewenste
// versnelling (of vertraging) op basis van de knoppen die zijn
// ingedrukt op de afstandsbediening.

void ZetGewensteSnelheidEnRichting (String laatsteKnop) {
  if (laatsteKnop.toFloat() >= 0) {    //numerieke toets
    gewensteSnelheid = laatsteKnop.toFloat();
    if (snelheid < gewensteSnelheid) { acceleratie = acceleratieStap; }
    if (snelheid > gewensteSnelheid) {acceleratie = - acceleratieStap; }
  }
  else {                               // niet een numerieke toets
    if (laatsteKnop == "-1STOP") {       // noodstop
      acceleratie = -snelheid;
      gewensteSnelheid = 0;
    }
    if (laatsteKnop == "-1>") {              // knop naar rechts
      if (richting == 1) {                   // omkering tijdens het rijden
        gewensteSnelheid = 0;                // eerst afremmen naar 0
        acceleratie = - acceleratieStap;
        gewensteRichting = 0;
        laatsteKnop ="";
      }
      else {                                 // rijrichting hetzelfde
        if (snelheid == gewensteSnelheid  && snelheid < 9 && richting == 0) {  // gewenste snelheid is bereikt en nog niet max
         gewensteSnelheid  += .5 ;             
         acceleratie = acceleratieStap;
        }
      }
    }
    if (laatsteKnop == "-1<") {              // knop naar links
      if (richting == 0) {                   // omkering tijdens het rijden
        gewensteSnelheid = 0;                // eerst afremmen naar 0
        acceleratie = - acceleratieStap;
        gewensteRichting = 1;
        laatsteKnop ="";
      }
      else {                                 // rijrichting hetzelfde
        if (snelheid == gewensteSnelheid  && snelheid < 9 && richting == 1 ) {  // gewenste snelheid is bereikt en nog niet max
         gewensteSnelheid += 0.5;             
         acceleratie = acceleratieStap;
        }
      }
    }
    if (laatsteKnop == "-1V") {
      if (snelheid == gewensteSnelheid  && snelheid > 0 ) {  // gewenste snelheid is bereikt en nog niet max
         gewensteSnelheid -= 0.25;             
         acceleratie = -acceleratieStap;
      }
    }
    if (laatsteKnop == "-1^") {
      if (snelheid == gewensteSnelheid  && snelheid < 9 ) {  // gewenste snelheid is bereikt en nog niet max
         gewensteSnelheid += 0.25;             
         acceleratie = acceleratieStap;
      }
    }
    if (laatsteKnop == "-1#") {
      snelheid = gewensteSnelheid;      // sla het accelereren/decelereren over: direct naar gewenste snelheid
    }
    if (laatsteKnop == "-1*" && snelheid < 9 - sprongWaarde) {
      sprong = sprongWaarde;            // zet "sprong" aan zolang deze toets is ingedrukt.
    }

   
    if (snelheid == 0 && gewensteSnelheid == 0) {
        if (laatsteKnop == "-1G<" ) {     // minimale stroom geluidsmodule aanzetten
        snelheid = geluidAan ;
        gewensteSnelheid = geluidAan;
        richting = 1;
        gewensteRichting = 1;
      }
      if (laatsteKnop == "-1G>" ) {     // minimale stroom geluidsmodule aanzetten
        snelheid = geluidAan ;
        gewensteSnelheid = geluidAan;
        richting = 0;
        gewensteRichting = 0;
      }
    }
   
  }
}

// ====

// ZET LED INDICATOREN - IR
// zet juiste waarden op LED pinnen: indicatoren voor acties die bezig zijn
// (richting, snelheidsverandering en stop)
void ZetLedIndicators (){
  if (snelheid  == 0) {
    for (t = 0; t < 2 ; t++) {
      ledStatus [t] =0 ;         // richting Leds uit
    }
    ledStatus [2] = 2;           // stop led aan
    ledStatus [richting] = 2;     // juiste richting led aan
  }
  else {                       // motor draait
    if (gewensteSnelheid == 0) {
      ledStatus [2] = 1;         // stop led laten knipperen
    } else {
      ledStatus [2] = 0;
    }
    if (gewensteRichting != richting) { //richting verandering gewenst
      ledStatus [gewensteRichting] = 1;  // gewenste richting knipperen
    } 
    else {
      ledStatus [1-gewensteRichting] = 0; // andere richtingsled uit
      if (gewensteSnelheid != snelheid) { // snelheidsverandering bezig (en niet naar 0)
        ledStatus [gewensteRichting] = 1;
      }
      else {
        ledStatus [gewensteRichting] = 2;
      }
    }
  }
}
// ===

// HAAL IR FUNCTIETOETS OP
int VertaalIRfunctie (String g) {
  int f = 0;
    if (g == "-1G01") {
        f = 1;                                       // functie 1
    }
    if (g == "-1G02") {
        f = 2;                                       // functie 2
    }
    if (g == "-1G03") {
        f = 3;                                       // functie 3
    }
      if (g == "-1G04") {
        f = 4;                                       // functie 4
    }
    if (g == "-1G05") {
         f = 5;                                       // functie 5
    }
    if (g == "-1G06") {
         f = 6;                                       // functie 6
    }
    return f;
}
// ===

// --------------- einde schets ----------------


--- Einde van code ---


De code voorziet in bediening van de pulsbreedte met potmeter en functietoetsen of met infrarood afstandsbediening. Standaard staat deze op "potmeter".


Lijst van onderdelen

De volgende onderdelen zijn gebruikt (aangegeven prijzen zijn Nederlandse prijzen)

* Voeding - step up/down 4A  | 4,95
* Motorcontroller 4A               | 4,95
* Arduino Nano met pinnen     | 5,95 (zonder pinnen, zelf solderen 4,95)
* Brugcel, gelijkrichter 6A       | 0,70
* Potmeter 10k ohm               | 0,50
* LEDje                                  | 0,10
* Weerstandje 1 k ohm           | 0,10
* Breadboard draadjes fem-fem | 3,95
* Druktoetsen 6x                     | 3,00 (0,50/stuk, prijs afhankelijk van type)
Totale prijs komt dan op 24,20, zonder verzendkosten.
Bij bestelling van (een deel) van de spullen bij tante Ali, kunnen de kosten flink omlaag (en levertijden omhoog). Zo heb ik 5 Arduino's gekocht voor $12. Deze Arduino's kunnen ook in de geluidsmodules worden gebruikt.


Enkele aanwijzingen voor de opbouw

Enig gereedschap is nodig, zoals een voltmeter (multimeter) voor het instellen van de voeding, een soldeerbout, een computer  met de Arduino software (de zogenaamde IDE, gratis te downloaden), en een USB kabel met mini USB (niet de micro USB van je telefoon, maar de iets grotere stekker).
Zoals gezegd: let op met de voeding: eerst het uitgangsvoltage instellen, dan pas andere spullen aansluiten.


Als de pulsbreedte besturing klaar is, kan elke analoge loc hierop rijden. Dus je hoeft niet te wachten op de geluidsmodules om deze rijstroom besturing te gebruiken.

Tot zover de bouwbeschrijving.

Rob

mark mms:
Rob, weer bedankt voor de info!

Ik ga eens bedenken of dit een betere oplossing is voor mijn analoog systeem.
Vooral geluid per trein en lichten aan en uit zetten zal doorslag geven.

Mvg mark

Navigatie

[0] Berichtenindex

[#] Volgende pagina

Naar de volledige versie