/* 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 ----------------
Zo vind ik het (misschien) ook wel leuk om met mijn treinen te rijden. 8)Ook wel lullig: heb je een modelspoorbaan en dan vind je het misschien wel leuk om met treinen rond te rijden. ::)
Voor het meten van de pulsbreedte en de veranderingen in de frequentie zijn twee (input) pinnen van de Arduino over weerstanden verbonden met de rijstroom voordat deze gelijk gericht is. Elke pin heeft 2 weerstanden: een van de rijstroom naar de pin en een van de pin naar de GND. Deze opstelling is er een zogenaamde spanningsdeler, ...
/* GELUIDSMODULE TESTER
* Testprogramma voor geluidsmodules voor analoge h0 trein
* Geeft aan welke signalen door de module worden herkend.
* Meet de puls op 2 pinnen verbonden met de rijstroom.
* Programma wacht op herkenbaar signaal op een van de pinnen.
* Bij herkenbaar signaal (d.w.z periode kleiner dan 2020 us
* en groter dan 0) wordt de rijpin en pulsbreedte in % weergegeven.
* Ook speciale frequenties voor de functies (1-6) worden herkend
* en aangegeven.
* Output op de seriële (USB) poort. Waarden zijn uit te lezen met
* de serial monitor op de computer.
*
* Alleen als de waarde verandert wordt een nieuwe regel met
* informatie 'geprint'.
*/
// ==> Geef hier de 2 pinnen op waarmee de rijstroom wordt gemeten <==
#define rijpin1 6
#define rijpin2 7
// --- DEFINITIES ----
#define pullup false // geeft aan of de interne pullup weerstand gebruikt moet worden
#define maxpulsbreedte 5000 // hoe lang wachten (minimaal 2x periode)
// Frequenties (Periodes) op de rijstroom
#define rijPeriode 2020 // rijstroom puls in us
#define functie_01_Periode 1500 // Periode (freq.) functie 1
#define functie_02_Periode 1250 // Periode (freq.) functie 2
#define functie_03_Periode 990 // Periode (freq.) functie 3
#define functie_04_Periode 790 // Periode (freq.) functie 4
#define functie_05_Periode 590 // Periode (freq.) functie 5
#define functie_06_Periode 490 // Periode (freq.) functie 6
#define pulsruis 40 // maximaal verschil in gemeten Periodes (ruis)
#define minhoog 200 // minimaal "hoog" signaal
#define elcoLaadtijd 1000 // oplaadtijd van de Elcos (ms) = tijd tot stabiele pulsmeting
// ---- VARIABLEN ----
int rijpin[] {rijpin1, rijpin2};
// pulse meting variabelen: lengte 'hoog', 'laag' en trillingstijd (periode). Alle tijden in us.
double pulsbreedteHoog;
double pulsbreedteLaag;
double pulsPeriode;
double pulsbreedteHoog2;
double pulsbreedteLaag2;
double pulsPeriode2;
int vooruit = 1; // richting: bepaalt welke pin wordt uitgelezen voor de rijstroom puls
int pulsbreedte = 0; // pulsbreedte in %
int vorigePulsbreedte = 0; // vorige pulsbreedte om verandering vast te stellen
int functie = 0; // speciale functie frequentie gemeten
int vorigeFunctie = 0;
void setup() {
pinMode (rijpin[0],INPUT);
digitalWrite(rijpin[0],pullup);
pinMode (rijpin[1],INPUT);
digitalWrite(rijpin[1],pullup);
Serial.begin(9600);
Serial.println("Geluidsmodule gestart.");
delay(elcoLaadtijd); // wacht op stabiele puls (na opladen Elco)
getSignaal(); // zoek naar signaal op de pinnen
}
void loop() {
// lees de huidige rijpin uit
pulsbreedteHoog = pulseIn(rijpin[vooruit], HIGH, maxpulsbreedte);
pulsbreedteLaag = pulseIn(rijpin[vooruit], LOW, maxpulsbreedte );
pulsbreedteHoog2 = pulseIn(rijpin[vooruit], HIGH, maxpulsbreedte);
pulsbreedteLaag2 = pulseIn(rijpin[vooruit], LOW, maxpulsbreedte );
pulsPeriode = pulsbreedteHoog + pulsbreedteLaag;
pulsPeriode2 = pulsbreedteHoog2 + pulsbreedteLaag2;
// beoordeel het signaal
if (pulsPeriode > rijPeriode + pulsruis || pulsPeriode < pulsruis ) {
// geen herkenbaar signaal meer
getSignaal(); // zoek naar signaal op een van de rojpinnen
vorigePulsbreedte = 0; // forceer weergave zodra signaal gevonden
} else
// herkenbaar signaal
{
// bepaal welk signaal (frequentie) is ontvangen en voer bijbehorende functie uit
if (abs (pulsPeriode - rijPeriode) < pulsruis) {
// normale rijstroom: bereken pulsbreedte (in %)
pulsbreedte = 100 * pulsbreedteHoog / rijPeriode;
}
functie = getFunctie();
// resultaten weegeven als er iets is veranderd.
if (abs(vorigePulsbreedte - pulsbreedte) > 1 || functie != vorigeFunctie ) {
// meer dan 1% pulsbreedte verschil of functietoets ingedrukt
Serial.print ("Rijpin: ");
Serial.print (vooruit + 1);
Serial.print (" || Pulsbreedte: ");
Serial.print (pulsbreedte);
Serial.print("% ");
Serial.print (" || Functie: ");
Serial.println(functie);
delay(10);
vorigePulsbreedte = pulsbreedte;
vorigeFunctie = functie;
}
}
}
// SIGNAAL ZOEKEN
// functie om te wachten op een herkenbaar signaal op een van de rijpinnen.
void getSignaal() {
Serial.println ("Module wacht op herkenbaar signaal.");
// zolang geen rijstroom periode en geen "hoog" signaal is gevonden
// blijft deze lus om-en-om op elk van de rijpinnenm meten.
do {
vooruit = (!vooruit); // wissel van rijpin
pulsbreedteHoog = pulseIn(rijpin[vooruit], HIGH, maxpulsbreedte);
pulsbreedteLaag = pulseIn(rijpin[vooruit], LOW , maxpulsbreedte);
pulsPeriode = pulsbreedteHoog + pulsbreedteLaag;
delay(50);
Serial.print("."); // elke poging: "."
delay(200);
} while (abs(pulsPeriode - rijPeriode) > pulsruis || pulsbreedteHoog < minhoog);
// Signaal gevonden. Geef dit aan op de seriële bus
Serial.println("!");
Serial.print("Herkenbaar signaal gevonden op rijpin ");
Serial.print(vooruit+1);
Serial.println(".");
}
// HERKEN FUNCTIE-FREQUENTIE
// functie voor het checken van functie-frequenties
// op de puls (functietoets).
int getFunctie () {
int f = 0;
if (abs (pulsPeriode - functie_01_Periode) < pulsruis && abs (pulsPeriode2 - functie_01_Periode) > pulsruis) { f = 1;}
if (abs (pulsPeriode - functie_02_Periode) < pulsruis && abs (pulsPeriode2 - functie_02_Periode) > pulsruis) { f = 2;}
if (abs (pulsPeriode - functie_03_Periode) < pulsruis && abs (pulsPeriode2 - functie_03_Periode) > pulsruis) { f = 3;}
if (abs (pulsPeriode - functie_04_Periode) < pulsruis && abs (pulsPeriode2 - functie_04_Periode) > pulsruis) { f = 4;}
if (abs (pulsPeriode - functie_05_Periode) < pulsruis && abs (pulsPeriode2 - functie_05_Periode) > pulsruis) { f = 5;}
if (abs (pulsPeriode - functie_06_Periode) < pulsruis && abs (pulsPeriode2 - functie_06_Periode) > pulsruis) { f = 6;}
return f;
}
// --- einde ---
/* DFPLAYER TESTER
* Testprogramma voor geluidsmodules voor analoge h0 trein
* Test de seriële communicatie met de DFplayer (MP3 speler)
*
* De communicatie gaat met "soft serial" op 2 digitale pinnen
* naar keuze. Het programma speelt de bestanden in volgorde
* af, te beginnen bij 001.mp3, dan 002.mp3, etc.
* Afspeeltijd per bestand is instelbaar.
*/
#define MP3RX 9 // serial receive pin, verbonden met transmit van DFplayer
#define MP3TX 8 // serial transmit pin, verbonden met receive van DFplayer
#define afspeeltijd 8000 // in ms
# define Start_Byte 0x7E
# define Version_Byte 0xFF
# define Command_Length 0x06
# define End_Byte 0xEF
# define Acknowledge 0x00 //Returns info with command 0x41 [0x01: info, 0x00: no info]
int LED = 13;
int x=0;
bool MP3play = false; // MP3 playing y/n
#include <SoftwareSerial.h>
SoftwareSerial MP3Serial(MP3RX, MP3TX); // RX, TX
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
MP3Serial.begin(9600);
pinMode(LED, OUTPUT);
digitalWrite (LED, HIGH);
execute_CMD(0x3F, 0, 0); // Send request for initialization parameters
delay (1000);
execute_CMD(0x06, 0, 28); // Set the volume to medium (0x00~0x30)
delay (100);
execute_CMD(0x07, 0, 0); //
delay (100);
}
void loop() {
// put your main code here, to run repeatedly:
if (MP3Serial.available()) { // er is iets aangekomen op de seriele bus
delay(20);
while(MP3Serial.available()) { // serieel uitlezen
Serial.print(MP3Serial.read(),HEX);
Serial.print(".");
}
Serial.println("||");
MP3play = false;
}
if (!MP3play) {
x++;
MP3play = true;
execute_CMD (0x03, 0, x);
delay(afspeeltijd);
MP3play=false;
}
}
// DF serial command code
void execute_CMD(byte CMD, byte Par1, byte Par2) // Excecute the command and parameters
{
// Calculate the checksum (2 bytes)
int16_t checksum = -(Version_Byte + Command_Length + CMD + Acknowledge + Par1 + Par2);
// Build the command line
byte Command_line[10] = { Start_Byte, Version_Byte, Command_Length, CMD, Acknowledge, Par1, Par2, checksum >> 8, checksum & 0xFF, End_Byte};
//Send the command line to the module
for (byte k=0; k<10; k++)
{
MP3Serial.write( Command_line[k]);
}
}
/* GELUIDSMODULE
* versie 0.9.2, Mei 2018 - Rob van Deursen
* Rijstroom afhankelijk geluid voor analoge modeltreinen.
* Module vereist rijstroom met pulsbreedte modulatie en heeft dan de volgende functies:
* - Startgeluid (starten van een motor, bijvoorbeeld
* - Stationair geluid
* - Rijstroom afhankelijke geluiden tijdens het rijden
* - 4 geluidsfuncties, te bedienen met frequentie-veranderingen op de rijstroom
* - 2 andere functies (licht schakelen, bijvoorbeeld)
* Per loc of treinstel zijn andere definities mogelijk voor de gebruikte pinnen op de
* Arduino en voor de geluiden op de MP3 speler (DFplayer).
* De geluiden staan in map "MP3" op de geluidskaart.
*/
// ----- DEFINITIES PER MODULE -----
// === V100 ===
// ----- Pin definities ------
#define pulsbreedtePin1 6 // digitale pin voor PWM rijspanning richting 1
#define pulsbreedtePin2 7 // digitale pin voor PWM rijspanning richting 2
#define lichtPin 11 // Liever niet pin 13, eventueel PWM = dimbaar licht.
#define MP3RX 9 // serieel receive (van MP3 speler)
#define MP3TX 8 // serieel transmit (naar MP3 speler
// ----- rijstroom en geluid/licht instellingen ------
#define aantalSnelheden 1.1 // aantal rijsnelheden (exclusief 0), 0 geeft stationair geluid
#define nulPWM 700.0 // PWM pulsbreedte (in us) om aanloopweerstand v.d. motor te overwinnen
#define stapPWM 150.0 // PWM pulsbreedte (in us) verschil om geluidstap te maken (2020 is 100%)
#define startgeluid 1 // 001.mp3
#define stationair 2 // 002.mp3
#define rijden1 3 // 003.mp3
#define geluidsfunctie1 4 // 004.mp3 (bel)
#define geluidsfunctie2 5 // 005.mp3 (Hoorn)
#define geluidsfunctie3 6 // 006.mp3 (kolen scheppen)
#define geluidsfunctie4 7 // 007.mp3 (motor afzetten)
#define lichtfunctie 5 // functie 5 is licht aan/uit
// MP3 speler (DFplayer)
#define volume 22 // geluidsvolume (0-47)
#define equalizer 0 // equaliser 0-5: normal, pop, rock, jazz, classic, base
/*
// === VT98 (RAILBUS) ===
// ----- Pin definities -----
#define pulsbreedtePin1 3 // digitale pin voor PWM rijspanning richting 1
#define pulsbreedtePin2 4 // digitale pin voor PWM rijspanning richting 2
#define lichtPin 11 // Liever niet pin 13, eventueel PWM = dimbaar licht.
//#define MP3RX 9 // serieel receive (van MP3 speler)
//#define MP3TX 8 // serieel transmit (naar MP3 speler
// ----- rijstroom en geluid/licht instellingen -----
#define aantalSnelheden 3.1 // aantal rijsnelheden (exclusief 0), 0 geeft stationair geluid
#define nulPWM 515.0 // PWM pulsbreedte (in us) om aanloopweerstand v.d. motor te overwinnen
#define stapPWM 210.0 // PWM pulsbreedte (in us) verschil om geluidstap te maken (2020 is 100%)
#define stationair 1 // 001.mp3
#define rijden1 2 // 002.mp3
#define rijden2 3 // 003.mp3
#define rijden3 4 // 004.mp3
#define startgeluid 5 // 005.mp3
#define geluidsfunctie1 8 // 008.mp3 (hoorn - lang)
#define geluidsfunctie2 7 // 007.mp3 (hoorn - kort)
#define geluidsfunctie3 0 // geen functie
#define geluidsfunctie4 6 // 006.mp3 (motor uitzetten)
#define lichtfunctie 6 // functie 6 is licht aan/uit
// MP3 speler (DFplayer)
#define volume 24 // geluidsvolume (0-47)
#define equalizer 5 // equaliser 0-5: normal, pop, rock, jazz, classic, base
*/
/*
// === BR50 ===
// ----- Pin definities -----
#define pulsbreedtePin1 3 // digitale pin voor PWM rijspanning richting 1
#define pulsbreedtePin2 5 // digitale pin voor PWM rijspanning richting 2
// LET OP! pin 5 lijkt niet de meeest betroubare pin
// hier zit ook een timer/count functie op waarvan het lijkt dat
// pdeze de ulsbreedte meting verstoort, met name bij het wisselen
// van de pulsbreedte!
#define lichtPin 11 // Liever niet pin 13, eventueel PWM = dimbaar licht.
#define MP3RX 7 // serieel receive (van MP3 speler)
#define MP3TX 6 // serieel transmit (naar MP3 speler
// ----- rijstroom en geluid/licht instellingen -----
#define aantalSnelheden 6.1 // aantal rijsnelheden (exclusief 0), 0 geeft stationair geluid
#define nulPWM 510.0 // PWM pulsbreedte (in us) om aanloopweerstand v.d. motor te overwinnen
#define stapPWM 150.0 // PWM pulsbreedte (in us) verschil om geluidstap te maken (2020 is 100%)
#define startgeluid 1 // 001.mp3
#define stationair 2 // 002.mp3
#define rijden1 3 // 003.mp3
#define rijden2 4 // 004.mp3
#define rijden3 5 // 005.mp3
#define rijden4 6 // 006.mp3
#define rijden5 7 // 008.mp3
#define rijden6 8 // 008.mp3
#define geluidsfunctie1 9 // 009.mp3 (fluit - kort)
#define geluidsfunctie2 10 // 010.mp3 (fluit - kort)
#define geluidsfunctie3 11 // 011.mp3 (kolen scheppen)
#define geluidsfunctie4 12 // 012.mp3 (nader te bepalen functie)
#define lichtfunctie 0 // geen licht functie
//MP3 speler (DFplayer)
#define volume 32 // geluidsvolume (0-47)
#define equalizer 0 // equaliser 0-5: normal, pop, rock, jazz, classic, base
*/
// ----- ALGEMENE DEFINITIES -----
// technische definities MP3 speler
#define Start_Byte 0x7E
#define Version_Byte 0xFF
#define Command_Length 0x06
#define End_Byte 0xEF
#define Acknowledge 0x00 //Returns info with command 0x41 [0x01: info, 0x00: no info]
// Definities voor de elektronica
#define elcoLaadtijd 800 // oplaadtijd van de Elcos (ms) = tijd tot stabiele pulsmeting
#define pullup false // gebruik van interne pullup weerstanden op rijpinnen ja/nee (true/false)
// Frequenties (Periodes) op de rijstroom
#define rijPeriode 2020 // rijstroom puls in us
#define functie_01_Periode 1500 // Periode (freq.) functie 1
#define functie_02_Periode 1250 // Periode (freq.) functie 2
#define functie_03_Periode 990 // Periode (freq.) functie 3
#define functie_04_Periode 790 // Periode (freq.) functie 4
#define functie_05_Periode 590 // Periode (freq.) functie 5
#define functie_06_Periode 490 // Periode (freq.) functie 6
#define pulsruis 40 // maximaal verschil in gemeten Periodes (ruis)
#define minhoog 200
// ---- VARIABELEN ----
int pulsbreedtePin[] {pulsbreedtePin1, pulsbreedtePin2};
double pulsbreedteHoog;
double pulsbreedteLaag;
double pulsbreedteHoog2;
double pulsbreedteLaag2;
double pulsPeriode;
double pulsPeriode2;
int lopendeFunctie = 0; // > 0 : er wordt een speciale functie uitgevoerd
int snelheid = 0;
int vorigeSnelheid = 0;
int vooruit = 1; // richting: bepaalt welke pin wordt uitgelezen voor de rijstroom puls
int MP3klaar; // geeft aan of MP3 speelt, , 0 = aan, 1 = uit.
int x = 0;
int geluidsfunctie [] {geluidsfunctie1, geluidsfunctie2, geluidsfunctie3, geluidsfunctie4};
int MP3count = 0; // teller om status op te vragen
// ---- libraries en objecten ----
#include <EEPROM.h> // EEPROM om licht aan/uit te onthouden
#include <SoftwareSerial.h> // // softserial voor mp3
SoftwareSerial MP3Serial(MP3RX, MP3TX); // RX, TX
// ----- Initialiseren -----
void setup() {
MP3Serial.begin(9600);
// Serial.begin(9600);
// Serial.println("Opstarten...");
pinMode (pulsbreedtePin[0],INPUT);
digitalWrite(pulsbreedtePin[0],pullup);
pinMode (pulsbreedtePin[1],INPUT);
digitalWrite(pulsbreedtePin[1],pullup);
pinMode (lichtPin,OUTPUT);
digitalWrite(lichtPin,EEPROM.read(0)); // licht aan of uit: waarde uit EEPROM
// gluidsmodule starten
execute_CMD(0x3F, 0, 0); // initialiseer MP3 speler
// Serial.println("MP3 speler initialisatie");
delay (80);
while (MP3status() == 0) { // wacht op antwoord
// Serial.println("Wacht op initialisatie");
delay (50);
}
execute_CMD(0x06, 0, volume); // zet het geluidsvolumevolume
delay (80);
execute_CMD(0x07, 0, equalizer); // equalizer
delay (80);
speelGeluid (startgeluid); // speel startgeluid af
// terwijl de MP3 speler start, wordt de richting alvast gemeten
delay(elcoLaadtijd); // wacht op stabiele puls (na opladen Elco)
do {
vooruit = (vooruit ==0 );
pulsbreedteHoog = pulseIn(pulsbreedtePin[vooruit], HIGH);
pulsbreedteLaag = pulseIn(pulsbreedtePin[vooruit], LOW );
pulsbreedteHoog2 = pulseIn(pulsbreedtePin[vooruit], HIGH);
pulsbreedteLaag2 = pulseIn(pulsbreedtePin[vooruit], LOW );
pulsPeriode = pulsbreedteHoog + pulsbreedteLaag;
pulsPeriode2 = pulsbreedteHoog2+ pulsbreedteLaag2;
// Serial.print("rijpin: ");
// Serial.print(vooruit + 1);
// Serial.print(" ");
// Serial.println(pulsbreedteHoog);
} while (pulsbreedteHoog < minhoog || pulsbreedteHoog2 < minhoog ); // "hoog" signaal is pin actief
}
void loop() {
do {
pulsbreedteHoog = pulseIn(pulsbreedtePin[vooruit], HIGH);
pulsbreedteLaag = pulseIn(pulsbreedtePin[vooruit], LOW );
pulsbreedteHoog2 = pulseIn(pulsbreedtePin[vooruit], HIGH);
pulsbreedteLaag2 = pulseIn(pulsbreedtePin[vooruit], LOW );
pulsPeriode = pulsbreedteHoog + pulsbreedteLaag;
pulsPeriode2 = pulsbreedteHoog2+ pulsbreedteLaag2;
// Serial.print("rijpin: ");
// Serial.print(vooruit + 1);
// Serial.print(" ");
// Serial.print(pulsPeriode);
// Serial.print(" / ");
// Serial.print(pulsbreedteHoog);
// Serial.print(" / ");
// Serial.print(pulsbreedteLaag);
// Serial.print(" || ");
// Serial.print(pulsPeriode2);
// Serial.print(" / ");
// Serial.print(pulsbreedteHoog2);
// Serial.print(" / ");
// Serial.println(pulsbreedteLaag2);
} while (pulsPeriode > rijPeriode + pulsruis || pulsbreedteHoog < minhoog || pulsbreedteLaag < pulsruis );
// bepaal welk signaal (frequentie) is ontvangen en voer bijbehorende functie uit
if (abs (pulsPeriode - rijPeriode) < pulsruis) {
// normale rijstroom
snelheid = getSnelheid(pulsbreedteHoog);
}
MP3klaar = (MP3status() == 1);
if (lopendeFunctie > 0) { // er loopt nog een speciale geluidsfunctie
if (MP3klaar) { // geluid voor een functie is afgespeeld
lopendeFunctie = 0; // gewoon geluid afspelen
}
}
//snelheid afhankelijk geluid
if (lopendeFunctie == 0) { // Er wordt geen speciaal geluid (meer) afgespeeld
lopendeFunctie = getFunctie();
// geluidsfunctie (1 - 6)
if (lopendeFunctie > 0) { // (geluids)functie gestart
lopendeFunctie = startFunctie(lopendeFunctie);
}
else {
// geen speciale functie nu, dus gewoon geluid spelen
if (snelheid != vorigeSnelheid || MP3klaar ) {
// er is een snelheidswissel of MP3 speelt niet meer
speelGeluid(snelheid+2); // geluidsbestand 002-008
vorigeSnelheid = snelheid;
}
}
}
}
//
//functie bepalen snelheid op basis van pulsbreedte
int getSnelheid(double pbr){
int s;
s = (pbr - nulPWM)/stapPWM;
s = constrain (s, 0, aantalSnelheden); // beperk de snelheidswaarde tussen 0 en het maximum
return s;
}
// functie voor het checken van functie-frequenties op de puls (functietoets)
int getFunctie () {
int f = 0;
if (abs (pulsPeriode - functie_01_Periode) < pulsruis && abs (pulsPeriode2 - functie_01_Periode) < pulsruis ) { f = 1;}
if (abs (pulsPeriode - functie_02_Periode) < pulsruis && abs (pulsPeriode2 - functie_02_Periode) < pulsruis ) { f = 2;}
if (abs (pulsPeriode - functie_03_Periode) < pulsruis && abs (pulsPeriode2 - functie_03_Periode) < pulsruis ) { f = 3;}
if (abs (pulsPeriode - functie_04_Periode) < pulsruis && abs (pulsPeriode2 - functie_04_Periode) < pulsruis ) { f = 4;}
if (abs (pulsPeriode - functie_05_Periode) < pulsruis && abs (pulsPeriode2 - functie_05_Periode) < pulsruis ) { f = 5;}
if (abs (pulsPeriode - functie_06_Periode) < pulsruis && abs (pulsPeriode2 - functie_06_Periode) < pulsruis ) { f = 6;}
return f;
}
// speciale functie starten
// geeft terug of de functie moet blijven lopen
int startFunctie(int f) {
int lopen = 0;
int gn;
if (f < 5 ){ // geluidsfunctie (1-4)
gn = geluidsfunctie [f-1]; // geluidsbestand nummer
//geluid afspelen
if (gn > 0) { // geluid is gedefinieerd (0 = geen geluid)
speelGeluid(gn);
lopen = f; // volgende functie wacht op aflopen MP3 geluid
}
}
else if (f == lichtfunctie) {
digitalWrite(lichtPin, (digitalRead (lichtPin) == LOW) ); // wissel hoog/laag (= aan/uit)
EEPROM.write(0,digitalRead (lichtPin)); // onthou licht aan of uit tot volgende opstart.
delay (100);
}
return lopen; // 0 = niet wachten, > 0 is wachten op einde geluid
}
// controleer of geluid is afgespeeld
// met I/O pin is "hoog" klaar
// zonder IO pin is het info ontvangen op soft serial
// Speel geluid af
// stuurt commando naar de MP3 speler
void speelGeluid(int bestandnummer) {
execute_CMD(0x03, 0, bestandnummer);
// Serial.print("Geluidsbestand gestart: ");
// Serial.println(bestandnummer);
MP3klaar = 0; // geluid speelt
delay (100);
}
// status MP3 speler lezen
// output: 0 = geen info
// 1 = mp3 klaar (speelt niet)
// 2 = mp3 speelt
// 3 = fout / onbekend
int MP3status () {
int m = 0;
int t = 0;
byte b;
int bstat; // status byte
int btrack; // bestand nummer
if ( !MP3Serial.available()) { // er is niets aangekomen op de seriele
MP3count ++;
if (MP3count > 30000 ) {
execute_CMD (0x4B,0,0); // query huidig bestand dat wordt afgespeeld
//delay (100);
MP3count = 0;
// Serial.println("status verzoek");
}
}
else { // er is iets op de seriele bus
delay(80);
while(MP3Serial.available()) { // serieel uitlezen
t++;
b = MP3Serial.read();
if (t == 4) { // dit is de status byte
bstat = b;
}
if (t == 7) { // dit is het bestandsnummer
btrack = b;
}
if (t == 10){ // meer dan 1 bericht
t=0;
}
// Serial.print(b,HEX);
// Serial.print(".");
}
switch (bstat) {
case 0x3F: // initialisatie parameters ontvangen
m = 2; // speler is bezig
break;
case 0x3D: // eind van een bestand
m = 1; // speler is klaar
break;
case 0x4B: // antwoord op bestand dat wordt afgespeeld
if (btrack > 0) {
m = 2; // bestand speelt
} else {
m = 1; // er speelt geen bestand, speler is kaar
}
break;
case 0x40: // fout in transmissie
delay(150); // even wachten
m = 1; // speler is klaar
default:
m = 3; // onbekend = fout
}
// Serial.print("||");
// Serial.print(bstat,HEX);
// Serial.print(" - ");
// Serial.print(btrack);
// Serial.print(" m: ");
// Serial.println(m);
return m;
}
}
/*
// Reset MP3 speler
void resetMP3() {
// Serial.print("MP3 module reset... ");
delay (100); // even wachten na de foutmelding, MP3 pseler is mogelijk aan het initialiseren.
execute_CMD(0x0C, 0, 0); // stuur reset commando
delay (50);
execute_CMD(0x3F, 0, 0); // initialiseer MP3 speler
// Serial.println("MP3 speler initialisatie");
delay (800);
execute_CMD(0x06, 0, volume); // zet het geluidsvolumevolume
delay (80);
execute_CMD(0x07, 0, equalizer); // equalizer
delay (80);
MP3klaar = 1; // er wordt geen bestand meer afgespeeld
}
*/
//===
// DF Seriële commando's versturen
void execute_CMD(byte CMD, byte Par1, byte Par2) // Excecute the command and parameters
{
// Bereken checksum (2 bytes)
int16_t checksum = -(Version_Byte + Command_Length + CMD + Acknowledge + Par1 + Par2);
// Bouw het commando op
byte Command_line[10] = { Start_Byte, Version_Byte, Command_Length, CMD, Acknowledge, Par1, Par2, checksum >> 8, checksum & 0xFF, End_Byte};
// Verstuur commando naar MP3 speler
for (byte k=0; k<10; k++)
{
MP3Serial.write( Command_line[k]);
}
}
--- EINDE ---
Is de volgende uitdaging de glaskast of köff?Oepfff… Gelukkig heb ik geen van beide in mijn verzameling :D
Ik heb even een vraagje. Kan je hier ook een "tjoek-tjoek" geluidje mee maken die zich aanpast aan de snelheid van een (analoge) trein? Ik ben al een tijdje op zoek naar een betaalbare oplossing hier voor.
/*
* RUISGENERATOR
* Stoomtrein geluiden met "puffen" van ruis.
* Testprogramma: langzaam versnellen van het puffen.
*/
#define Ruispin 10
#define Startfreq 2000 // laagste frequentie ruis
#define Eindfreq 4000 // hoogste frequentie ruis
#define pauze 0.33 // factor puf/pauze
unsigned int puf = 1000; // lengte puf-slag (ms)
void maakPuf(unsigned int lengte, unsigned int laag, unsigned int hoog) {
unsigned int freq;
unsigned long mils;
mils = millis() + (1-pauze) * lengte;
while (millis() < mils) {
freq = random (laag, hoog);
tone (Ruispin,freq);
}
noTone(Ruispin);
delay (lengte * pauze);
}
void setup() {
pinMode (Ruispin,OUTPUT);
}
void loop() {
// viercylinder = 4 puf slagen met verschil in eerste en laatste slag
maakPuf(puf, Startfreq + 100, Eindfreq + 250);
maakPuf(puf, Startfreq, Eindfreq);
maakPuf(puf, Startfreq, Eindfreq);
maakPuf(puf, Startfreq - 50 , Eindfreq - 100);
if (puf > 120) {
puf = puf * 0.90;
}
}
/*
* RUISGENERATOR STOOMTREIN
* Stoomtrein geluiden met rijstroom afhankelijk "puffen" van ruis.
*
* Eenvoudige extra geluidsfuncties:
* 1: fluitje (lijkt meer op een telefoon)
* 2: sissen
* 3: remmen
* 4: 4 seconde stilte (vrijloop)
* Functies werken redlijk bij langzaam rijden en goed bij stilstand en snel rijden
*
* versie 0.9.1 - 7 jul 2018
* toegevoegd:
* begrenzing puf tijd (voorkomen negatieve tijdsduur)
* rijstroommeting en functie bepalen in de puf-pauze
*/
// --- DEFINITIES ----
// pin definities
#define Ruispin 0 // pin voor aansturen van speaker
#define rijpin1 1
#define rijpin2 2
//geluidsdefinities
#define Startfreq 1800 // laagste frequentie ruis
#define Eindfreq 4000 // hoogste frequentie ruis
#define pauze 0.25 // factor puf/pauze
#define RemLaag 3200 // frequentiebereik voor remgeluid
#define RemHoog 3800
#define SisLaag 4000 // frequentiebereik voor sisgeluid
#define SisHoog 5500
// definities voor de meting van de rijstroom
#define pullup false // geeft aan of de interne pullup weerstand gebruikt moet worden
#define maxpulsbreedte 5000 // hoe lang wachten (minimaal 2x periode)
#define pulsbreedtestil 22 // pulsbreedte in % waaronder loc stil staat
// Frequenties (Periodes) op de rijstroom
#define rijPeriode 2020 // rijstroom puls in us
#define functie_01_Periode 1500 // Periode (freq.) functie 1
#define functie_02_Periode 1250 // Periode (freq.) functie 2
#define functie_03_Periode 990 // Periode (freq.) functie 3
#define functie_04_Periode 790 // Periode (freq.) functie 4
#define functie_05_Periode 590 // Periode (freq.) functie 5 - niet gebruikt
#define functie_06_Periode 490 // Periode (freq.) functie 6 - niet gebruikt
#define pulsruis 100 // maximaal verschil in gemeten Periodes (ruis)
#define minhoog 200 // minimaal "hoog" signaal
// ---- VARIABLEN ----
// puf-geluid variabelen: 4 slagen (is tweezijdige tweecylinder loc)
unsigned int ruisStartFreq[] {Startfreq + 120, Startfreq, Startfreq, Startfreq + 300 }; // hoogste frequentie puf-ruis per slag
unsigned int ruisEindFreq[] {Eindfreq - 50, Eindfreq, Eindfreq, Eindfreq - 120 }; // laagste frequentie puf-ruis per slag
int slag = 0;
// rijstroom variabelen
int rijpin[] {rijpin1, rijpin2};
int vooruit = 1; // richting: bepaalt welke pin wordt uitgelezen voor de rijstroom puls
double pulsbreedteHoog;
double pulsbreedteLaag;
double pulsPeriode;
int pulsbreedte = 0; // pulsbreedte in %
int functie = 0; // speciale functie frequentie gemeten
unsigned int puf; // lengte puf-slag (ms)
unsigned long pze; // pauze tot aan klok stand(ms)
// --- FUNCTIES ---
// Functie: maak puf geluid (één slag)
// Geeft ruis voor een deel van de opgegeven lengte en stil voor de resterende tijd (factor definitie)
// De ruisfrequentie neemt langzaam af om enigszins de volume afname te simuleren.
// input: lengte van de slag (in ms)
// laagste frequentie van de ruis
// hoogste frequentie van de ruis
// output: tijd tot einde pauze van de puf
unsigned long maakPuf(int lengte, unsigned int laag, unsigned int hoog) {
unsigned int freq;
unsigned long mils;
constrain (lengte,10,1000); // beperk de slag tussen 10ms en 1s.
float factor = 1 - (0.09/lengte);
mils = millis() + (1-pauze) * lengte;
while (millis() < mils) {
freq = random (laag, hoog);
tone (Ruispin,freq);
laag = laag*factor;
hoog = hoog*factor;
}
noTone(Ruispin);
return millis() + (lengte * pauze); // pauze tijd tussen de puffen
}
// Functie: Afspelen van ruis.
// Gebruikt voor sissen en remgeluid. Constant ruis-geluid gedurende de opgegeven lengte (in ms).
// input: lengte van de slag (in ms)
// laagste frequentie van de ruis
// hoogste frequentie van de ruis
void speelRuis(unsigned int lengte, unsigned int laag, unsigned int hoog) {
unsigned int freq;
unsigned long mils;
mils = millis() + lengte;
while (millis() < mils) {
freq = random (laag, hoog);
tone (Ruispin,freq);
}
noTone(Ruispin);
}
// Functie: Afspelen van een 'fluitje'
// Afwisselend een hoge en lage frequentie met een kleine frequentie variatie.
// input: lengte (in ms)
void speelFluitje(unsigned int lengte) {
unsigned int freq;
unsigned long mils;
mils = millis() + lengte;
while (millis() < mils) {
tone (Ruispin,random (2100,2120));
delay (20);
tone (Ruispin,random (2400,2430));
delay (18);
}
noTone(Ruispin);
}
void meetPuls() {
// puls meting variabelen: lengte 'hoog', 'laag' en trillingstijd (periode). Alle tijden in us.
pulsbreedteHoog = pulseIn(rijpin[vooruit], HIGH, maxpulsbreedte);
pulsbreedteLaag = pulseIn(rijpin[vooruit], LOW, maxpulsbreedte );
pulsPeriode = pulsbreedteHoog + pulsbreedteLaag;
}
// HERKEN FUNCTIE-FREQUENTIE
// functie voor het checken van functie-frequenties
// op de puls (functietoets).
int getFunctie () {
int f = 0;
if (abs (pulsPeriode - functie_01_Periode) < pulsruis) { f = 1;}
if (abs (pulsPeriode - functie_02_Periode) < pulsruis) { f = 2;}
if (abs (pulsPeriode - functie_03_Periode) < pulsruis) { f = 3;}
if (abs (pulsPeriode - functie_04_Periode) < pulsruis) { f = 4;}
return f;
}
void setup() {
pinMode (Ruispin,OUTPUT);
pinMode (rijpin[0],INPUT);
digitalWrite(rijpin[0],pullup);
pinMode (rijpin[1],INPUT);
digitalWrite(rijpin[1],pullup);
meetPuls();
speelRuis (950, SisLaag,SisHoog); // sissen
}
void loop() {
vooruit = !vooruit;
// Pulsbreedte bepalen
meetPuls();
pulsbreedte = 100 * pulsbreedteHoog / pulsPeriode;
functie = getFunctie();
if (functie) {
switch (functie) {
case 1:
speelFluitje(1800); // fluitje afspelen, 1,8 sec.
break;
case 2:
speelRuis (3000, SisLaag,SisHoog); // sissen, 3 sec.
break;
case 3:
speelRuis (2600, RemLaag,RemHoog); // remgeluid 2,6 sec.
break;
case 4:
pze = millis()+ 4000; // 4 sec. stilte
break;
}
}
else {
// rijgeluid
// tweecylinder = 4 puf slagen met verschil in eerste en laatste slag
if (pulsbreedte > pulsbreedtestil && millis() > pze) { // lok rijdt en niet in puf-pauze of stilte
puf = map(100 * sqrt (pulsbreedte), 550, 990, 700, 10);
pze = maakPuf(puf, ruisStartFreq [slag], ruisEindFreq [slag]);
if (slag < 3) {
slag++;
}
else {
slag = 0;
}
}
}
}
... Ik denk dat ik een beetje aangestoken ben door je laatste projectje met de digispark. Dit is precies wat ik voor ogen had.Ik wordt gaandeweg ook meegesleept in DigiSpark MP3loze versie, Pierre. Met name voor de boemels is dit de beste oplossing.
Als ik er mee aan de gang ga mag ik je dan op het forum om hulp vragen zodat er misschien nog meer mensen baat bij hebben?
...Ik ben woest aan het schilderen en popel om de soldeerbout te pakken. Ik moet me beheersen. ;D...En dan moet je straks van de meester eerst met breadboard en jumper kabeltjes aan de slag voor je mag solderen ;)
/*
* RUISGENERATOR STOOMTREIN
* Stoomtrein geluiden met rijstroom afhankelijk "puffen" van ruis. Voor analoog rijden met geluid.
* Rijstroom met pulsbreedtebesturing is nodig: de pulsbreedte wordt omgerekend naar puf-snelheid.
*
* Eenvoudige extra geluidsfuncties:
* 1: fluitje (lijkt meer op een telefoon)
* 2: sissen
* 3: remmen
* 4: stilte (vrijloop)
* Functies werken redelijk bij langzaam rijden en goed bij stilstand en snel rijden
*
* versie 1.0 - 16 jul 2018
*/
// --- DEFINITIES ----
// kies de loc om te compileren: zet precies één definitie op 'true'
#define BR57 false
#define BR70 true
#define BR91 false
// pin definities
#define Ruispin 1 // pin voor aansturen van speaker: pin 1 of 0 (0 = 5 sec. vertraging)
#define rijpin1 2 // rijstroom meting
#define rijpin2 4 // rijstroom meting
//geluidsdefinities per type loc
#if BR57
// definities voor slagen BR57. ("paa tsjie paa tsjoe...")
#define Startfreq1 1400 // laagste frequentie ruis slag 1
#define Eindfreq1 3400 // hoogste frequentie ruis slag 1
#define Startfreq2 2100 // laagste frequentie ruis slag 2
#define Eindfreq2 4800 // hoogste frequentie ruis slag 2
#define Startfreq3 1400 // laagste frequentie ruis slag 3
#define Eindfreq3 3400 // hoogste frequentie ruis slag 3
#define Startfreq4 1200 // laagste frequentie ruis slag 4
#define Eindfreq4 3000 // hoogste frequentie ruis slag 4
// berekening snelheid
#define pulsbreedtestil 26 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax 80 // pulsbreedte waar de maximum snelheid (pufritme) wordt bereikt
#define langstePuf 440 // langste puf (in ms) - langzaam rijden
#define kortstePuf 60 // kortste puf (in ms) - topsnelheid (minimum ligt rond 50ms)
// opstart geluid
#define BeginSis 1150 // lengte van het sisgeluid bij starten (en korte stroomonderbrekingen)
#endif
#if BR70
// definities voor slagen BR70 ("tsjoe, tsjie, tsjoe, tsjie")
#define Startfreq1 1700 // laagste frequentie ruis slag 1
#define Eindfreq1 3900 // hoogste frequentie ruis slag 1
#define Startfreq2 2000 // laagste frequentie ruis slag 2
#define Eindfreq2 4100 // hoogste frequentie ruis slag 2
#define Startfreq3 1720 // laagste frequentie ruis slag 3
#define Eindfreq3 3930 // hoogste frequentie ruis slag 3
#define Startfreq4 1980 // laagste frequentie ruis slag 4
#define Eindfreq4 4050 // hoogste frequentie ruis slag 4
// berekening snelheid
#define pulsbreedtestil 28 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax 65 // pulsbreedte waar de maximum snelheid (pufritme) wordt bereikt
#define langstePuf 375 // langste puf (in ms) - langzaam rijden
#define kortstePuf 50 // kortste puf (in ms) - topsnelheid (minimum ligt rond 50ms)
// opstart geluid
#define BeginSis 1150 // lengte van het sisgeluid bij starten (en korte stroomonderbrekingen)
#endif
#if BR91
// definities voor slagen BR91: 1e wat hoger, laatste wat lager dan de 2 middelste slagen ("tsjie, tsja, tsja, tsjoe")
#define Startfreq1 1950 // laagste frequentie ruis slag 1
#define Eindfreq1 4350 // hoogste frequentie ruis slag 1
#define Startfreq2 1800 // laagste frequentie ruis slag 2
#define Eindfreq2 4000 // hoogste frequentie ruis slag 2
#define Startfreq3 1800 // laagste frequentie ruis slag 3
#define Eindfreq3 4000 // hoogste frequentie ruis slag 3
#define Startfreq4 1750 // laagste frequentie ruis slag 4
#define Eindfreq4 3900 // hoogste frequentie ruis slag 4
// berekening snelheid
#define pulsbreedtestil 26 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax 84 // pulsbreedte waar de maximum snelheid (pufritme) wordt bereikt
#define langstePuf 800 // langste puf (in ms) - langzaam rijden
#define kortstePuf 71 // kortste puf (in ms) - topsnelheid (minimum ligt rond 50ms)
// opstart geluid
#define BeginSis 1750 // lengte van het sisgeluid bij starten (en korte stroomonderbrekingen)
#endif
// algemene geluidsdefinities
#define pauze 0.25 // factor puf/pauze (elke slag heeft voor een deel stilte)
#define RemLaag 3200 // frequentiebereik voor remgeluid
#define RemHoog 3800
#define SisLaag 4000 // frequentiebereik voor sisgeluid
#define SisHoog 5500
// definities voor de meting van de rijstroom
#define pullup false // geeft aan of de interne pullup weerstand gebruikt moet worden
#define maxpulsperiode 5000 // hoe lang wachten (minimaal 2x periode rijstroom PWM)
// Frequenties (Periodes) op de rijstroom
#define rijPeriode 2020 // rijstroom puls in us
#define functie_01_Periode 1500 // Periode (freq.) functie 1
#define functie_02_Periode 1250 // Periode (freq.) functie 2
#define functie_03_Periode 990 // Periode (freq.) functie 3
#define functie_04_Periode 790 // Periode (freq.) functie 4
#define functie_05_Periode 590 // Periode (freq.) functie 5 - niet gebruikt
#define functie_06_Periode 490 // Periode (freq.) functie 6 - niet gebruikt
#define pulsruis 100 // maximaal verschil in gemeten Periodes (ruis)
#define minhoog 200 // minimaal "hoog" signaal
// --- CONSTANTES ---
const float sqrtpbstil = 100*sqrt(pulsbreedtestil);
const float sqrtpbmax = 100*sqrt(pulsbreedtemax);
// ---- VARIABLEN ----
// puf-geluid variabelen: 4 slagen (is tweezijdige tweecylinder loc)
unsigned int ruisStartFreq[] {Startfreq1, Startfreq2, Startfreq3, Startfreq4}; // hoogste frequentie puf-ruis per slag
unsigned int ruisEindFreq[] {Eindfreq1, Eindfreq2, Eindfreq3, Eindfreq4 }; // laagste frequentie puf-ruis per slag
int slag = 0;
// rijstroom variabelen
int rijpin[] {rijpin1, rijpin2};
int vooruit = 1; // richting: bepaalt welke pin wordt uitgelezen voor de rijstroom puls
double pulsbreedteHoog;
double pulsbreedteLaag;
double pulsPeriode;
float pulsbreedte = 0; // pulsbreedte in %
int functie = 0; // speciale functie frequentie gemeten
unsigned int puf; // lengte puf-slag (ms)
unsigned long pze; // pauze tot aan klok stand(ms)
// --- FUNCTIES ---
// Functie: maak puf geluid (één slag)
// Geeft ruis voor een deel van de opgegeven lengte en stil voor de resterende tijd (factor definitie)
// De ruisfrequentie neemt langzaam af om enigszins de volume afname te simuleren.
// input: lengte van de slag (in ms)
// laagste frequentie van de ruis
// hoogste frequentie van de ruis
// output: tijd tot einde pauze van de puf
unsigned long maakPuf(int lengte, unsigned int laag, unsigned int hoog) {
unsigned int freq;
unsigned long mils;
float factor = 1 - (0.09/lengte);
mils = millis() + (1-pauze) * lengte;
while (millis() < mils) {
freq = random (laag, hoog);
tone (Ruispin,freq);
laag = laag*factor;
hoog = hoog*factor;
}
noTone(Ruispin);
return millis() + (lengte * pauze); // pauze tijd tussen de puffen
}
// Functie: Afspelen van ruis.
// Gebruikt voor sissen en remgeluid. Constant ruis-geluid gedurende de opgegeven lengte (in ms).
// input: lengte van de slag (in ms)
// laagste frequentie van de ruis
// hoogste frequentie van de ruis
void speelRuis(unsigned int lengte, unsigned int laag, unsigned int hoog) {
unsigned int freq;
unsigned long mils;
mils = millis() + lengte;
while (millis() < mils) {
freq = random (laag, hoog);
tone (Ruispin,freq);
}
noTone(Ruispin);
}
// Functie: Afspelen van een 'fluitje'
// Afwisselend een hoge en lage frequentie met een kleine frequentie variatie.
// input: lengte (in ms)
void speelFluitje(unsigned int lengte) {
unsigned int freq;
unsigned long mils;
mils = millis() + lengte;
while (millis() < mils) {
tone (Ruispin,random (2100,2120));
delay (20);
tone (Ruispin,random (2400,2430));
delay (18);
}
noTone(Ruispin);
}
void meetPuls() {
// puls meting variabelen: lengte 'hoog', 'laag' en trillingstijd (periode). Alle tijden in us.
pulsbreedteHoog = pulseIn(rijpin[vooruit], HIGH, maxpulsperiode);
pulsbreedteLaag = pulseIn(rijpin[vooruit], LOW, maxpulsperiode );
pulsPeriode = pulsbreedteHoog + pulsbreedteLaag;
}
// HERKEN FUNCTIE-FREQUENTIE
// functie voor het checken van functie-frequenties
// op de puls (functietoets).
int getFunctie () {
int f = 0;
if (abs (pulsPeriode - functie_01_Periode) < pulsruis) { f = 1;}
if (abs (pulsPeriode - functie_02_Periode) < pulsruis) { f = 2;}
if (abs (pulsPeriode - functie_03_Periode) < pulsruis) { f = 3;}
if (abs (pulsPeriode - functie_04_Periode) < pulsruis) { f = 4;}
return f;
}
void setup() {
pinMode (Ruispin,OUTPUT);
pinMode (rijpin[0],INPUT);
digitalWrite(rijpin[0],pullup);
pinMode (rijpin[1],INPUT);
digitalWrite(rijpin[1],pullup);
speelRuis (BeginSis, SisLaag,SisHoog); // sissen bij opstarten
}
void loop() {
// Pulsbreedte bepalen
vooruit = !vooruit; // wissel de pin waarop de rijstroom wordt gemeten
meetPuls();
pulsbreedte = 100 * pulsbreedteHoog / pulsPeriode;
functie = getFunctie();
// speciale geluidsfunctie gevonden
if (functie) {
// als speciale functie is gevonden, controleer de functie frequentie nogmaals.
// Hiermee wordt onterecht meten voorkomen (door bijvoorbeeld storing op de stroomopname).
meetPuls();
if (functie == getFunctie()) { // nog steeds dezelfde funtie op de rijstrrom
switch (functie) { // speel functie 1, 2, 3 of 4.
case 1:
speelFluitje(1800); // fluitje afspelen, 1,8 sec.
break;
case 2:
speelRuis (3000, SisLaag,SisHoog); // sissen, 3 sec.
break;
case 3:
speelRuis (3600, RemLaag,RemHoog); // remgeluid 3,6 sec.
break;
case 4:
pze = millis()+ 4500; // 4,5 sec. stilte = vrijloop
break;
}
}
}
else { // geen speciale functie, dan rij-geluid
// rijgeluid
// tweecylinder = 4 puf slagen met verschil in de slagen (volgens definities van de loc)
if (pulsbreedte > pulsbreedtestil && millis() > pze) { // lok rijdt en er is nu geen puf-pauze of vrijloop
// puf slag berekenen
if (pulsbreedte > pulsbreedtemax) {
pulsbreedte = pulsbreedtemax;
}
puf = map(100 * sqrt (pulsbreedte), sqrtpbstil, sqrtpbmax, langstePuf, kortstePuf); // reken pulssbreedte % om naar puf-tijd
pze = maakPuf(puf, ruisStartFreq [slag], ruisEindFreq [slag]); // maak puf-ruis. Functie geeft resterende pauze-tijd terug
// volgende puf-slag (volgnummer 0-3)
if (slag < 3) {
slag++;
}
else {
slag = 0;
}
}
} // einde functie spelen / rijgeluid
} // einde hoofd-lus
... (een tafel-loep staat nu op het verlanglijstje!).
Wat betreft rekenen aan elektronica: het is niet zo belangrijk maar die 220 ohm weerstanden in de spanningsdeler om de PWM aan te passen voor de ATTiny, dat zal wel goed gaan, maar als ik zo kijk kun je in plaats van 220 ohm minstens net zo goed 1k gebruiken. Scheelt weer wat mA in het gebruik.
Misschien wat overdadig, maar het werkt.
Andersom is het ook zo: als er eenmaal geluid in een van de locs zit, is het niet meer zo leuk om met een geluidloze loc te rijden ::) Geluid in de loc went snel: je mist het niet todat je het hebt...
Dus toen ik eenmaal was begonnen, moest ik wel door ;D
U zijt gewaarschuwd...
@Pierre , overweeg je nog om tzt ook diesels van geluid te voorzien, of hou je het bij de tsjoekende stomers?
Kan ik dan gewoon een soort diesel geluid met een DigiSpark genereren zonder MP3 speler?gaat niet lukken. Voor diesels zit je toch echt aan een MP3 speler vast (en ik ook). Kun je alvast aan het idee wennen.
#define pulsbreedtestil 34 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax 72 // pulsbreedte waar de maximum snelheid (pufritme) wordt bereikt
#define langstePuf 280 // langste puf (in ms) - langzaam rijden
#define kortstePuf 56 // kortste puf (in ms) - topsnelheid (minimum ligt rond 50ms)
De eerste instelling is de pulsbreedte waarbij de loc gaat rijden. Met "pulsbreedtemax" wordt de pulsbreedte bij de maximale (schaal)snelheid gedefinieerd.http://drazzy.com/package_drazzy.com_index.json
Rob ... is het niet mogelijk ergens op de print een baantje kaal te krabben/slijpen om een draadje aan te solderen? Dat moet toch te doen zijn met een beetje pielen.Dat was ook mijn gedachte, maar die MP3 speler is zo compact dat ik geen aanknooppunten kan vinden. Zoals bijvoorbeeld bij deze, waar rechtsonder de aansluiting kapot is. Dit is de enige plek waar ik de 5V kan terugvinden (nu dus niet meer).
/*
* RUISGENERATOR STOOMTREIN
* Stoomtrein geluiden met rijstroom afhankelijk "puffen" van ruis. Voor analoog rijden met geluid.
* Rijstroom met pulsbreedtebesturing is nodig: de pulsbreedte wordt omgerekend naar puf-snelheid.
*
* Eenvoudige extra geluidsfuncties:
* 1: fluitje (lijkt meer op een telefoon) - uit voor sommige modellen
* 2: sissen
* 3: remmen
* 4: stilte (vrijloop)
* Functies werken redelijk bij langzaam rijden en goed bij stilstand en snel rijden
*
* versie 1.3 - 19 sep 2018
*/
// --- DEFINITIES ----
// kies de loc om te compileren: zet precies één definitie op 'true'
#define BR38 false
#define BR64 false // nieuwste versie nog niet geladen
#define BR70 false // @ ATtiny (van DigiSpark)
#define BR78 false
#define BR91 true // @ ATtiny (los). Bootloader branden met BOD op 4.3V en clock op 16 MHz
#define ruisPin 1 // pin voor aansturen van speaker: pin 1 of 0 (0 = 5 sec. vertraging)
#define rijPin1 2 // rijstroom meting
#define rijPin2 4 // rijstroom meting
//geluidsdefinities per type loc
#if BR38
// definities voor slagen BR38. ("paa tsjie poe tsjoe...")
#define Startfreq1 1000 // laagste frequentie ruis slag 1
#define Eindfreq1 3000 // hoogste frequentie ruis slag 1
#define Startfreq2 1240 // laagste frequentie ruis slag 2
#define Eindfreq2 5400 // hoogste frequentie ruis slag 2
#define Startfreq3 800 // laagste frequentie ruis slag 3
#define Eindfreq3 2200 // hoogste frequentie ruis slag 3
#define Startfreq4 900 // laagste frequentie ruis slag 4
#define Eindfreq4 4500 // hoogste frequentie ruis slag 4
// berekening snelheid
#define pulsbreedtestil 34 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax 72 // pulsbreedte waar de maximum snelheid (pufritme) wordt bereikt
#define langstePuf 280 // langste puf (in ms) - langzaam rijden
#define kortstePuf 56 // kortste puf (in ms) - topsnelheid (minimum ligt rond 50ms)
// opstart geluid
#define BeginSis 2150 // lengte van het sisgeluid bij starten (en korte stroomonderbrekingen)
#endif
#if BR64
// definities voor slagen BR64. ("paa tsjie paa tsjoe...")
#define Startfreq1 1000 // laagste frequentie ruis slag 1
#define Eindfreq1 3000 // hoogste frequentie ruis slag 1
#define Startfreq2 1300 // laagste frequentie ruis slag 2
#define Eindfreq2 5500 // hoogste frequentie ruis slag 2
#define Startfreq3 1000 // laagste frequentie ruis slag 3
#define Eindfreq3 3000 // hoogste frequentie ruis slag 3
#define Startfreq4 940 // laagste frequentie ruis slag 4
#define Eindfreq4 2500 // hoogste frequentie ruis slag 4
// berekening snelheid
#define pulsbreedtestil 32 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax 56 // pulsbreedte waar de maximum snelheid (pufritme) wordt bereikt
#define langstePuf 190 // langste puf (in ms) - langzaam rijden
#define kortstePuf 60 // kortste puf (in ms) - topsnelheid (minimum ligt rond 50ms)
// opstart geluid
#define BeginSis 3530 // lengte van het sisgeluid bij starten (en korte stroomonderbrekingen)
#endif
#if BR70
// definities voor slagen BR70 ("tsjoe, tsjie, tsjoe, tsjie")
#define Startfreq1 1700 // laagste frequentie ruis slag 1
#define Eindfreq1 3900 // hoogste frequentie ruis slag 1
#define Startfreq2 2000 // laagste frequentie ruis slag 2
#define Eindfreq2 4100 // hoogste frequentie ruis slag 2
#define Startfreq3 1720 // laagste frequentie ruis slag 3
#define Eindfreq3 3930 // hoogste frequentie ruis slag 3
#define Startfreq4 1980 // laagste frequentie ruis slag 4
#define Eindfreq4 4050 // hoogste frequentie ruis slag 4
// berekening snelheid
#define pulsbreedtestil 28 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax 65 // pulsbreedte waar de maximum snelheid (pufritme) wordt bereikt
#define langstePuf 375 // langste puf (in ms) - langzaam rijden
#define kortstePuf 50 // kortste puf (in ms) - topsnelheid (minimum ligt rond 50ms)
// opstart geluid
#define BeginSis 1150 // lengte van het sisgeluid bij starten (en korte stroomonderbrekingen)
#endif
#if BR78
// definities voor slagen BR78. ("paa tsjoe paa tsjie...")
#define Startfreq1 1000 // laagste frequentie ruis slag 1
#define Eindfreq1 3000 // hoogste frequentie ruis slag 1
#define Startfreq2 900 // laagste frequentie ruis slag 2 900
#define Eindfreq2 4500 // hoogste frequentie ruis slag 2 2500
#define Startfreq3 1000 // laagste frequentie ruis slag 3
#define Eindfreq3 3000 // hoogste frequentie ruis slag 3
#define Startfreq4 1240 // laagste frequentie ruis slag 4
#define Eindfreq4 5400 // hoogste frequentie ruis slag 4
// berekening snelheid
#define pulsbreedtestil 34 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax 64 // pulsbreedte waar de maximum snelheid (pufritme) wordt bereikt
#define langstePuf 290 // langste puf (in ms) - langzaam rijden
#define kortstePuf 58 // kortste puf (in ms) - topsnelheid (minimum ligt rond 50ms)
// opstart geluid
#define BeginSis 1800 // lengte van het sisgeluid bij starten (en korte stroomonderbrekingen)
#endif
#if BR91
#define rijPin1 3 // rijstroom meting, afwijkende pin
// definities voor slagen BR91: 1e hoog, laatste wat lager dan de 2 middelste slagen ("tsjie, tsja, tsja, tsjoe")
#define Startfreq1 1500 // laagste frequentie ruis slag 1
#define Eindfreq1 4850 // hoogste frequentie ruis slag 1
#define Startfreq2 1800 // laagste frequentie ruis slag 2
#define Eindfreq2 4000 // hoogste frequentie ruis slag 2
#define Startfreq3 1800 // laagste frequentie ruis slag 3
#define Eindfreq3 4000 // hoogste frequentie ruis slag 3
#define Startfreq4 1750 // laagste frequentie ruis slag 4
#define Eindfreq4 3900 // hoogste frequentie ruis slag 4
// berekening snelheid
#define pulsbreedtestil 34 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax 82 // pulsbreedte waar de maximum snelheid (pufritme) wordt bereikt
#define langstePuf 260 // langste puf (in ms) - langzaam rijden
#define kortstePuf 60 // kortste puf (in ms) - topsnelheid (minimum ligt rond 50ms)
// opstart geluid
#define BeginSis 1750 // lengte van het sisgeluid bij starten (en korte stroomonderbrekingen)
#endif
// algemene geluidsdefinities
#define pauze 0.33 // factor puf/pauze (elke slag heeft voor een deel stilte)
//#define RemLaag 3200 // frequentiebereik voor remgeluid
//#define RemHoog 3800
#define RemLaag 3000 // frequentiebereik voor remgeluid
#define RemHoog 3600
#define SisLaag 3000 // frequentiebereik voor sisgeluid
#define SisHoog 5500
// definities voor de meting van de rijstroom
#define pullup false // geeft aan of de interne pullup weerstand gebruikt moet worden
#define maxpulsperiode 5000 // hoe lang wachten (minimaal 2x periode rijstroom PWM)
// Frequenties (Periodes) op de rijstroom
#define rijPeriode 2020 // rijstroom puls in us
#define functie_01_Periode 1500 // Periode (freq.) functie 1
#define functie_02_Periode 1250 // Periode (freq.) functie 2
#define functie_03_Periode 990 // Periode (freq.) functie 3
#define functie_04_Periode 790 // Periode (freq.) functie 4
#define functie_05_Periode 590 // Periode (freq.) functie 5 - niet gebruikt
#define functie_06_Periode 450 // Periode (freq.) functie 6 - niet gebruikt
#define pulsruis 80 // maximaal verschil in gemeten Periodes (ruis)
#define minhoog 100 // minimaal "hoog" signaal
// --- CONSTANTES ---
const float sqrtpbstil = 100*sqrt(10);
const float sqrtpbmax = 100*sqrt(10+pulsbreedtemax-pulsbreedtestil);
// ---- VARIABLEN ----
// puf-geluid variabelen: 4 slagen (is tweezijdige tweecylinder loc)
unsigned int ruisStartFreq[] {Startfreq1, Startfreq2, Startfreq3, Startfreq4}; // hoogste frequentie puf-ruis per slag
unsigned int ruisEindFreq[] {Eindfreq1, Eindfreq2, Eindfreq3, Eindfreq4 }; // laagste frequentie puf-ruis per slag
int slag = 0;
// rijstroom variabelen
int rijpin[] {rijPin1, rijPin2};
int vooruit = 1; // richting: bepaalt welke pin wordt uitgelezen voor de rijstroom puls
double pulsbreedteHoog;
double pulsbreedteLaag;
double pulsPeriode;
float pulsbreedte = 0; // pulsbreedte in %
int functie = 0; // speciale functie frequentie gemeten
unsigned int puf; // lengte puf-slag (ms)
unsigned long pze; // pauze tot aan klok stand(ms)
// --- FUNCTIES ---
// Functie: maak puf geluid (één slag)
// Geeft ruis voor een deel van de opgegeven lengte en stil voor de resterende tijd (factor definitie)
// De ruisfrequentie neemt langzaam af om enigszins de volume afname te simuleren.
// input: lengte van de slag (in ms)
// laagste frequentie van de ruis
// hoogste frequentie van de ruis
// output: tijd tot einde pauze van de puf
unsigned long maakPuf(int lengte, unsigned int laag, unsigned int hoog) {
unsigned int freq;
unsigned long mils;
float factor = 1 - (0.09/lengte);
mils = millis() + (1-pauze) * lengte;
while (millis() < mils) {
freq = random (laag, hoog);
tone (ruisPin,freq);
laag = laag*factor;
hoog = hoog*factor;
}
noTone(ruisPin);
return millis() + (lengte * pauze); // pauze tijd tussen de puffen
}
// Functie: Afspelen van ruis.
// Gebruikt voor sissen en remgeluid. Constant ruis-geluid gedurende de opgegeven lengte (in ms).
// input: lengte van de slag (in ms)
// laagste frequentie van de ruis
// hoogste frequentie van de ruis
void speelRuis(unsigned int lengte, unsigned int laag, unsigned int hoog) {
unsigned int freq;
unsigned long mils;
mils = millis() + lengte;
while (millis() < mils) {
freq = random (laag, hoog);
tone (ruisPin,freq);
}
noTone(ruisPin);
}
// Functie: Afspelen van een 'fluitje'
// Afwisselend een hoge en lage frequentie met een kleine frequentie variatie.
// input: lengte (in ms)
void speelFluitje(unsigned int lengte) {
unsigned int freq;
unsigned long mils;
mils = millis() + lengte;
while (millis() < mils) {
tone (ruisPin,random (2100,2120));
delay (20);
tone (ruisPin,random (2400,2430));
delay (18);
}
noTone(ruisPin);
}
// MEET DE PULS OP DE RiJSTROOM
void meetPuls() {
// puls meting variabelen: lengte 'hoog', 'laag' en trillingstijd (periode). Alle tijden in us.
pulsbreedteHoog = pulseIn(rijpin[vooruit], HIGH, maxpulsperiode);
pulsbreedteLaag = pulseIn(rijpin[vooruit], LOW, maxpulsperiode );
pulsPeriode = pulsbreedteHoog + pulsbreedteLaag;
}
// HERKEN FUNCTIE-FREQUENTIE
// functie voor het checken van functie-frequenties
// op de puls (functietoets).
int getFunctie () {
int f = 0;
if (abs (pulsPeriode - functie_01_Periode) < pulsruis) { f = 1;}
if (abs (pulsPeriode - functie_02_Periode) < pulsruis) { f = 2;}
if (abs (pulsPeriode - functie_03_Periode) < pulsruis) { f = 3;}
if (abs (pulsPeriode - functie_04_Periode) < pulsruis) { f = 4;}
return f;
}
void setup() {
pinMode (ruisPin,OUTPUT);
pinMode (rijpin[0],INPUT);
digitalWrite(rijpin[0],pullup);
pinMode (rijpin[1],INPUT);
digitalWrite(rijpin[1],pullup);
delay(100); // even wachten op opladen elco (stabiele voeding)
speelRuis (BeginSis, SisLaag,SisHoog); // sissen bij opstarten
}
void loop() {
// Pulsbreedte bepalen
vooruit = !vooruit; // wissel de pin waarop de rijstroom wordt gemeten
do {
vooruit = !vooruit; // wissel de pin waarop de rijstroom wordt gemeten
meetPuls();
} while (pulsbreedteHoog < minhoog || pulsbreedteLaag < pulsruis); // 'hoog' signaal alleen op actieve rijpin
pulsbreedte = 100 * pulsbreedteHoog / pulsPeriode;
functie = getFunctie();
// speciale geluidsfunctie gevonden
if (functie) {
// als speciale functie is gevonden, controleer de functie frequentie nogmaals.
// Hiermee wordt onterecht meten voorkomen (door bijvoorbeeld storing op de stroomopname).
delay (5); // korte pauze tussen de metingen
meetPuls();
if (functie == getFunctie()) { // nog steeds dezelfde funtie op de rijstrrom
switch (functie) { // speel functie 1, 2, 3 of 4.
#if BR70
case 1:
speelFluitje(1800); // fluitje afspelen, 1,8 sec.
break;
#endif
case 2:
speelRuis (3000, SisLaag,SisHoog); // sissen, 3 sec.
break;
case 3:
speelRuis (3600, RemLaag,RemHoog); // remgeluid 3,6 sec.
break;
case 4:
pze = millis()+ 4500; // 4,5 sec. stilte = vrijloop
break;
}
}
}
else { // geen speciale functie, dan rij-geluid
// rijgeluid
// tweecylinder = 4 puf slagen met verschil in de slagen (volgens definities van de loc)
if (pulsbreedte > pulsbreedtestil && millis() > pze) { // lok rijdt en er is nu geen puf-pauze of vrijloop
// puf slag berekenen
if (pulsbreedte > pulsbreedtemax) {
pulsbreedte = pulsbreedtemax;
}
puf = map(100 * sqrt (10+pulsbreedte-pulsbreedtestil), sqrtpbstil, sqrtpbmax, langstePuf, kortstePuf); // reken pulssbreedte % om naar puf-tijd
pze = maakPuf(puf, ruisStartFreq [slag], ruisEindFreq [slag]); // maak puf-ruis. Functie geeft resterende pauze-tijd terug
// volgende puf-slag (volgnummer 0-3)
if (slag < 3) {
slag++;
}
else {
slag = 0;
}
}
} // einde functie spelen / rijgeluid
} // einde hoofd-lus
/* GELUIDSMODULE
* Rijstroom afhankelijk geluid voor analoge modeltreinen.
* Module vereist rijstroom met pulsbreedte modulatie en heeft dan de volgende functies:
* - Startgeluid (starten van een motor, bijvoorbeeld
* - Stationair geluid
* - Rijstroom afhankelijke geluiden tijdens het rijden
* - Tot 6 geluidsfuncties, te bedienen met frequentie-veranderingen op de rijstroom
* - 1 lichtschakel functie (op één van de 6 functies)
* Per loc of treinstel worden de pinnen, snelheid en geluiden gedefinieerd.
* De geluiden staan per set (loc) in in map op de de geheugenkaart, d.w.z.
* - voor één loc is alleen map "01" op de geheugenkaart van de MP3 speler beschikbaar.
* - voor een geluidswagon worden mappen "01" t/m "06" gebruikt: één set per loc.
*/
#define versie "2.0, 7 Oktober 2018 - Rob van Deursen"
// ----- ALGEMENE DEFINITIES -----
// ----- definities voor het compileren -----
// definieer voor welke geluidsmodule wordt gecompileerd (zet deze op "true"), selecteer 1 module.
// voor DigiSpark: zet in IDE "board" op "Digispark (default 16.5 MHz)" by compileren / uploaden.
#define BR24 false // BR24 @ Digispark
#define BR50 false // BR50 @ Arduino
#define BR57 false // BR57 @ ATtiny (gebruikt bibliotheken voor Arduino) - BOD op 2.7v
#define BR78 false // BR78 @ Digispark
#define V100 false // V100 @ Arduino
#define V160 false // V160 @ DigiSpark
#define VT98 true // VT98 @ Arduino (railbus)
#define geluidswagon false // Tot 6 locs. Nu 5 locs: BR70, BR38, BR24, V60 en V160 @ Arduino
// probleemoplosser zet informatie op de seriele bus (seriele monitor). Zet deze aan bij het oplossen van problemen
#define probleemoplosser false // diverse status info naar seriele monitor j/n (werkt niet voor DigiSpark)
// ----- algemene MP3 en functietoets indeling ------
// geluidsbestanden 001.mp3 t/m 006.mp3: speciale geluidsfuncties
// 009.mp3: startgeluid
// 010.mp3: stationair
// 011.mp3 en hoger: rijgeluiden (opvolgende snelheden)
#define startgeluid 9 // 009.mp3
#define stationair 10 // 010.mp3
// rijden vanaf bestand 011.mp3 en hoger (opvolgend na stationair)
#define geluidsfunctie1 1 // 001.mp3 fluit of hoorn
#define geluidsfunctie2 2 // 002.mp3 bel (of korte fluit/hoorn)
#define geluidsfunctie3 3 // 003.mp3 rem of vrijloop (afhankelijk van loc of treinstel)
#define geluidsfunctie4 4 // 004.mp3 stoom afblazen of motor uitzetten
// geluidsfuncties 5 en 6: gedefinieerd per geluidsmodule
// EEPROM geheugenlocaties
#define licht1adr 0
#define licht2adr 1
#define geluidadr 2
// ----- DEFINITIES PER GELUIDSMODULE -----
// === BR24 @ DigiSpark ===
#if BR24
#define DigiSpark true
// ----- pin definities ------
// pin 3 op DigiSpark niet gebruiken: heeft 1k5 pullup naar 5V en USB
#define rijPin1 1 // digitale pin voor PWM rijspanning richting 1 met LED
#define rijPin2 4 // digitale pin voor PWM rijspanning richting 2
#define MP3RX 2 // serieel receive (van MP3 speler)
#define MP3TX 0 // serieel transmit (naar MP3 speler)
//#define lichtPin - geen lichtfunctie DigiSpark
// ----- rijstroom en geluid/licht instellingen -----
#define aantalSnelheden 5 // aantal snelheidsstappen loc
#define pulsbreedtestil 26 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax 56 // pulsbreedte waarbij de maximum snelheid wordt bereikt
#define geluidsfunctie5 5 // 005.mp3, waterpomp
#define geluidsfunctie6 6 // 006.mp3, kolen scheppen
#define lichtfunctie 0 // geen lichtfunctie
#define lichtsterkte 0 // lichtsterkte (0-255)
//MP3 speler (DFplayer)
#define volume 28 // geluidsvolume (0-47)
#define equalizer 0 // equaliser 0-5: normal, pop, rock, jazz, classic, base
#define MP3monster 0 // bemonster intervaltijd MP3 speler (ms) (0 = geen)
#define geluid 1 // geluid altijd aan in map "01"
#endif
// === BR50 @ Arduino ===
#if BR50
#define Arduino true
// ----- pin definities ------
#define rijPin1 3 // digitale pin voor PWM rijspanning richting 1
#define rijPin2 5 // digitale pin voor PWM rijspanning richting 2
#define MP3RX 7 // serieel receive (van MP3 speler)
#define MP3TX 6 // serieel transmit (naar MP3 speler)
#define lichtPin 11 //
// ----- rijstroom en geluid/licht instellingen -----
#define aantalSnelheden 8 // aantal snelheidsstappen loc
#define pulsbreedtestil 26 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax 66 // pulsbreedte waarbij de maximum snelheid wordt bereikt
#define geluidsfunctie5 5 // 005.mp3, korte fluit
#define geluidsfunctie6 6 // 006.mp3, kolen scheppen
#define lichtfunctie 0 // geen lichtfunctie
#define lichtsterkte 0 // lichtsterkte (0-255)
//MP3 speler (DFplayer)
#define volume 28 // geluidsvolume (0-47)
#define equalizer 5 // equaliser 0-5: normal, pop, rock, jazz, classic, base
#define MP3monster 3000 // bemonster intervaltijd MP3 speler (ms) (0 = geen)
#define geluid 1 // geluid altijd aan in map "01" van MP3 speler.
#define MP3inittijd 1500 // initialisatietijd MP3 speler (ms)
#endif
// === BR57 @ ATtiny ===
#if BR57
#define ATtiny true
// ----- pin definities ------
#define rijPin1 1 // digitale pin voor PWM rijspanning richting 1
#define rijPin2 2 // digitale pin voor PWM rijspanning richting 2
#define MP3RX 4 // serieel receive (van MP3 speler)
#define MP3TX 3 // serieel transmit (naar MP3 speler)
#define lichtPin 0 //
// ----- rijstroom en geluid/licht instellingen -----
#define aantalSnelheden 7 // aantal snelheidsstappen loc
#define pulsbreedtestil 22 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax 76 // pulsbreedte waarbij de maximum snelheid wordt bereikt
#define geluidsfunctie5 5 // 005.mp3, korte fluit
#define geluidsfunctie6 6 // 006.mp3, Veiligheidsventiel
#define lichtfunctie 0 // geen lichtfunctie
#define lichtsterkte 0 // lichtsterkte (0-255)
//MP3 speler (DFplayer)
#define volume 23 // geluidsvolume (0-47)
#define equalizer 5 // equaliser 0-5: normal, pop, rock, jazz, classic, base
#define MP3monster 3000 // bemonster intervaltijd MP3 speler (ms) (0 = geen)
#define geluid 1 // geluid altijd aan in map "01" van MP3 speler.
#endif
// === BR78 @ DigiSpark ===
#if BR78
#define DigiSpark true
// ----- pin definities ------
// pin 3 op DigiSpark niet gebruiken: heeft 1k5 pullup naar 5V en USB
#define rijPin1 1 // digitale pin voor PWM rijspanning richting 1 met LED
#define rijPin2 4 // digitale pin voor PWM rijspanning richting 2
#define MP3RX 2 // serieel receive (van MP3 speler)
#define MP3TX 0 // serieel transmit (naar MP3 speler)
//#define lichtPin - geen lichtfunctie DigiSpark
// ----- rijstroom en geluid/licht instellingen -----
#define aantalSnelheden 8 // aantal snelheidsstappen loc
#define pulsbreedtestil 30 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax 70 // pulsbreedte waarbij de maximum snelheid wordt bereikt
#define geluidsfunctie5 5 // 005.mp3, korte fluit
#define geluidsfunctie6 6 // 006.mp3, kolen scheppen
#define lichtfunctie 0 // geen lichtfunctie
#define lichtsterkte 0 // lichtsterkte (0-255)
//MP3 speler (DFplayer)
#define volume 25 // geluidsvolume (0-47)
#define equalizer 0 // equaliser 0-5: normal, pop, rock, jazz, classic, base
#define MP3monster 0 // bemonster intervaltijd MP3 speler (ms) (0 = geen)
#define geluid 1 // geluid altijd aan in map "01"
#endif
// === V100 @ Arduino ===
#if V100
#define Arduino true
// ----- pin definities ------
#define rijPin1 6 // digitale pin voor PWM rijspanning richting 1
#define rijPin2 7 // digitale pin voor PWM rijspanning richting 2
#define MP3RX 9 // serieel receive (van MP3 speler)
#define MP3TX 8 // serieel transmit (naar MP3 speler)
#define lichtPin 11 // licht
// ----- rijstroom en geluid/licht instellingen -----
#define aantalSnelheden 1 // aantal snelheidsstappen loc
#define pulsbreedtestil 33 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax 40 // pulsbreedte waarbij de maximum snelheid wordt bereikt
#define geluidsfunctie5 0 // 0 = geen geluidsfunctie
#define geluidsfunctie6 6 // 006.wav
#define lichtfunctie 5 // lichtfunctie op 5 (kabineverlichting aan/uit)
#define lichtsterkte 200 // lichtsterkte (0-255)
//MP3 speler (DFplayer)
#define volume 22 // geluidsvolume (0-47)
#define equalizer 0 // equaliser 0-5: normal, pop, rock, jazz, classic, base
#define MP3monster 0 // bemonster intervaltijd MP3 speler (ms) (0 = geen)
#define geluid 1 // geluid altijd aan in map "01"
#endif
// === V160 @ DigiSpark ===
#if V160
#define DigiSpark true
// ----- pin definities ------
#define rijPin1 1 // digitale pin voor PWM rijspanning richting 1 met LED
#define rijPin2 4 // digitale pin voor PWM rijspanning richting 2
#define MP3RX 2 // serieel receive (van MP3 speler)
#define MP3TX 0 // serieel transmit (naar MP3 speler)
//#define lichtPin - geen lichtfunctie DigiSpark
// ----- rijstroom en geluid/licht instellingen -----
#define aantalSnelheden 3 // aantal snelheidsstappen loc
#define pulsbreedtestil 19 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax 61 // pulsbreedte waarbij de maximum snelheid wordt bereikt
#define geluidsfunctie5 5 // 005.mp3
#define geluidsfunctie6 6 // 006.mp3
#define lichtfunctie 0 // geen lichtfunctie
#define lichtsterkte 0 // lichtsterkte (0-255)
//MP3 speler (DFplayer)
#define volume 32 // geluidsvolume (0-47)
#define equalizer 1 // equaliser 0-5: normal, pop, rock, jazz, classic, base
#define MP3monster 0 // bemonster intervaltijd MP3 speler (ms) (0 = geen)
#define geluid 1 // geluid altijd aan in map "01"
#endif
// === VT98 (RAILBUS) @ Arduino ===
#if VT98
#define Arduino true
// ----- pin definities ------
#define rijPin1 6 // digitale pin voor PWM rijspanning richting 1 met LED
#define rijPin2 7 // digitale pin voor PWM rijspanning richting 2
#define MP3RX 9 // serieel receive (van MP3 speler)
#define MP3TX 8 // serieel transmit (naar MP3 speler)
#define lichtPin 11 // licht
// ----- rijstroom en geluid/licht instellingen -----
#define aantalSnelheden 3 // aantal snelheidsstappen loc
#define pulsbreedtestil 26 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax 72 // pulsbreedte waarbij de maximum snelheid wordt bereikt
#define geluidsfunctie5 5 //
#define geluidsfunctie6 0 // geen geluid (alleen lichtfunctie)
#define lichtfunctie 6 // lichtfunctie op 6
#define lichtsterkte 255 // lichtsterkte (0-255)
//MP3 speler (DFplayer)
#define volume 24 // geluidsvolume (0-47)
#define equalizer 5 // equaliser 0-5: normal, pop, rock, jazz, classic, base
#define MP3monster 0 // bemonster intervaltijd MP3 speler (ms) (0 = geen)
#define geluid 1 // geluid altijd aan in map "01"
#endif
// === GELUIDSWAGON (tot maximaal 6 geluiden sets) @ Arduino ===
// geluidswagon werkt als volgt:
// Met functie 1 t/m 6 wordt de geluids-set aan gezet. Voor elke loc of treinstel is er een set (map) op de MP3 speler.
// Geluid kan worden uitgezet met functie nummer gedefinieerd met selecteerGeluidUit (standaard is dit functie 4),
// Om een andere loc te kiezen: zet het geluid uit, en druk vervolgens 1 seconde op de functietoets van de nieuwe loc.
// Zodra deze aan is, begint het startgeluid van de loc. Daarna werkt het rijgeluid en de geluidsfuncties.
// Let op: serieel TX/RX anders dan bij andere Arduino modules
#if geluidswagon
#define uitgebreidLicht true // meerdere lichtfuncties
#define Arduino true
// ----- pin definities ------
#define rijPin1 6 // digitale pin voor PWM rijspanning richting 1
#define rijPin2 7 // digitale pin voor PWM rijspanning richting 2
#define MP3RX 8 // serieel receive (van MP3 speler)
#define MP3TX 9 // serieel transmit (naar MP3 speler)
#define lichtPin 10 // (PWM) pin voor licht (sluitlichten)
#define lichtPin2 11 // (PWM) pin voor licht (binnenverlichting)
// ----- rijstroom en geluid/licht instellingen -----
// loc 01: BR70
#define aantalSnelhedenLoc01 8 // aantal snelheidsstappen loc
#define pulsbreedtestil01 26 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax01 64 // pulsbreedte waarbij de maximum snelheid wordt bereikt
// loc 02: BR38
#define aantalSnelhedenLoc02 8 // aantal snelheidsstappen loc
#define pulsbreedtestil02 30 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax02 72 // pulsbreedte waarbij de maximum snelheid wordt bereikt
// loc 03: BR24
#define aantalSnelhedenLoc03 5 // aantal snelheidsstappen loc
#define pulsbreedtestil03 26 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax03 56 // pulsbreedte waarbij de maximum snelheid wordt bereikt
// loc 04: V60
#define aantalSnelhedenLoc04 2 // aantal snelheidsstappen loc
#define pulsbreedtestil04 25 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax04 45 // pulsbreedte waarbij de maximum snelheid wordt bereikt
// loc 05: V160
#define aantalSnelhedenLoc05 3 // aantal snelheidsstappen loc
#define pulsbreedtestil05 26 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax05 56 // pulsbreedte waarbij de maximum snelheid wordt bereikt
// loc 06
#define aantalSnelhedenLoc06 0 // aantal snelheidsstappen loc
#define pulsbreedtestil06 22 // pulsbreedte in % waaronder loc stil staat
#define pulsbreedtemax06 72 // pulsbreedte waarbij de maximum snelheid wordt bereikt
// gezamenlijke definities
#define geluidsfunctie5 0 // (0 = geen functie)
#define geluidsfunctie6 0 // (0 = geen functie)
#define selecteerGeluidUit 4 // selecteer geluid uit met deze functie (geluid gaat weer aan met toets 1 t/m 6 per loc)
#define lichtfunctie 5 // functie 5 is sluitlicht aan/uit
#define lichtsterkte 20 // lichtsterkte (0-255)
#define lichtfunctie2 6 // functie 6 is binnenverlichting aan/uit
#define lichtsterkte2 50 // lichtsterkte (0-255)
// MP3 speler (DFplayer)
#define volume 18 // geluidsvolume (0-47)
#define equalizer 1 // equaliser 0-5: normal, pop, rock, jazz, classic, base
#define MP3monster 0 // bemonster intervaltijd MP3 speler (ms) (0 = geen)
#endif
// Frequenties (Periodes) op de rijstroom
#define rijPeriode 2020 // rijstroom puls in us
#if ATtiny
#define functie_01_Periode 1350 // Periode (freq.) functie 1
#define functie_02_Periode 1190 // Periode (freq.) functie 2
#else
#define functie_01_Periode 1500 // Periode (freq.) functie 1
#define functie_02_Periode 1250 // Periode (freq.) functie 2
#endif
#define functie_03_Periode 990 // Periode (freq.) functie 3
#define functie_04_Periode 790 // Periode (freq.) functie 4
#define functie_05_Periode 590 // Periode (freq.) functie 5
#define functie_06_Periode 450 // Periode (freq.) functie 6
// ----- ALGEMENE DEFINITIES -----
// technische definities MP3 speler
#define Start_Byte 0x7E
#define Version_Byte 0xFF
#define Command_Length 0x06
#define End_Byte 0xEF
#define Acknowledge 0x00
// Definities voor de elektronica
#define pullup false // geeft aan of de interne pullup weerstand gebruikt moet worden
#define maxpulsperiode 5000 // hoe lang wachten (minimaal 2x periode rijstroom PWM)
#if !MP3inittijd
#define MP3inittijd 1000 // initialisatietijd MP3 speler (ms)
#endif
#if DigiSpark
#define pulsruis 80 // maximaal verschil in gemeten Periodes (ruis)
#define minhoog 90 // minimaal "hoog" signaal
#else
#define pulsruis 70
#define minhoog 100 // minimaal "hoog" signaal
#endif
// ---- libraries en objecten ----
// kies juist serial bibliotheek voor Arduino c.q. Digispark
#if (DigiSpark) // DigiSpark definities
#include <SoftSerial.h> // SoftSerial en TinyPinChange voor DigiSpark
#include <TinyPinChange.h>
SoftSerial MP3Serial(MP3RX, MP3TX); // RX, TX
#else // Arduino definities (ook voor ATTiny)
#include <EEPROM.h> // EEPROM om licht aan/uit en geluid aan/uit te onthouden
#include <SoftwareSerial.h> // SoftwareSerial voor mp3 op Arduino
SoftwareSerial MP3Serial(MP3RX, MP3TX); // RX, TX
#endif
// --- CONSTANTES EN VARIABELEN---
// ----- voor alle configuraties -----
// rijstroom variabelen
int rijpin[] {rijPin1, rijPin2};
int vooruit = 1; // richting: bepaalt welke pin wordt uitgelezen voor de rijstroom puls
double pulsbreedteHoog;
double pulsbreedteLaag;
double pulsPeriode;
float pulsbreedte = 0; // pulsbreedte in %
int snelheid = 0;
int vorigeSnelheid = 0;
const float sqrtpbstil = 100*sqrt(10); // basiswaarde omrekenen pulsbreedte naar snelheid
// variabelen voor speciale functies op de rijstroom
int functie = 0; // speciale functie frequentie gemeten
int lopendeFunctie = 0; // > 0 : er wordt een speciale functie uitgevoerd
int licht; // licht sterkte of uit (0);
int licht2; // licht sterkte of uit (0);
// variabelen voor de MP3 speler
int MP3speler; // geeft MP3 status aan (van MP3Status functie) 0=geen info, 1=klaar, 2=speelt, 4=fout
long unsigned int MP3count = 0; // millis waarde om status MP3 speler op te vragen
int geluidsfunctie [] {geluidsfunctie1, geluidsfunctie2, geluidsfunctie3, geluidsfunctie4, geluidsfunctie5, geluidsfunctie6};
// ----- configuratie afhankelijk -----
// voor de geluidswagon zijn definities als array variabelen opgenomen, omdat deze per geluid set (loc) verschillend zijn.
// geluidsmodules voor een enkele loc of treinstel hebben deze waarden als een enkele, vaste definitie.
#if geluidswagon // geluidswagon tot 6 verschillende geluiden, andere slechts 1
int aantalSnelheden[] {aantalSnelhedenLoc01, aantalSnelhedenLoc02, aantalSnelhedenLoc03, aantalSnelhedenLoc04,aantalSnelhedenLoc05, aantalSnelhedenLoc06};
int pulsbreedtestil[] {pulsbreedtestil01, pulsbreedtestil02, pulsbreedtestil03, pulsbreedtestil04, pulsbreedtestil05, pulsbreedtestil06};
int pulsbreedtemax[] {pulsbreedtemax01, pulsbreedtemax02, pulsbreedtemax03, pulsbreedtemax04, pulsbreedtemax05, pulsbreedtemax06 };
int geluidAanteller = 0; // teller om geluid aan te zetten (tijd tussen2x dezelfde functietoets indrukken)
int geluid = 0; // geluid volgnummer (0 = uit)
float sqrtpbmax[] { // maximale pulsbreedte omgerekend
100*sqrt(10+pulsbreedtemax01 - pulsbreedtestil01),
100*sqrt(10+pulsbreedtemax02 - pulsbreedtestil02),
100*sqrt(10+pulsbreedtemax03 - pulsbreedtestil03),
100*sqrt(10+pulsbreedtemax04 - pulsbreedtestil04),
100*sqrt(10+pulsbreedtemax05 - pulsbreedtestil05),
100*sqrt(10+pulsbreedtemax06 - pulsbreedtestil06),
};
#else
const float sqrtpbmax = 100*sqrt(10+pulsbreedtemax - pulsbreedtestil); // maximale pulsbreedte omgerekend
#endif
// --- FUNCTIES ---
// RIJSTROOM PULSMETING
// Meet de rijstroom op een van de pinnen en geeft vult de gemeten pulswaarden in.
void meetPuls() {
// puls meting variabelen: lengte 'hoog', 'laag' en trillingstijd (periode). Alle tijden in us.
pulsbreedteHoog = pulseIn(rijpin[vooruit], HIGH, maxpulsperiode);
pulsbreedteLaag = pulseIn(rijpin[vooruit], LOW, maxpulsperiode );
pulsPeriode = pulsbreedteHoog + pulsbreedteLaag;
}
// ===
// HERKEN FUNCTIE-FREQUENTIE
// functie voor het checken van functie-frequenties
// op de puls (functietoets).
int getFunctie () {
int f = 0;
if (abs (pulsPeriode - functie_01_Periode) < pulsruis) { f = 1;}
if (abs (pulsPeriode - functie_02_Periode) < pulsruis) { f = 2;}
if (abs (pulsPeriode - functie_03_Periode) < pulsruis) { f = 3;}
if (abs (pulsPeriode - functie_04_Periode) < pulsruis) { f = 4;}
if (abs (pulsPeriode - functie_05_Periode) < pulsruis) { f = 5;}
if (abs (pulsPeriode - functie_06_Periode) < pulsruis) { f = 6;}
return f;
}
//===
// START SPECIALE FUNCTIE
// Bekijkt of er een geluidsdefinitie is voor de opgegeven functie en start deze.
// Geeft terug of de geluidsfunctie gestart is (en moet blijven lopen).
// input: functie nummer (1-6)
// output: functie nummer (als gestart), anders 0
int startFunctie(int f) {
int lopen = 0; // volgende functie wacht op aflopen MP3 geluid
//geluid afspelen?
if (geluidsfunctie [f-1] > 0){ // geluid is gedefinieerd (0 = geen geluid)
speelGeluid(geluid, geluidsfunctie [f-1]);
lopen = f; // als er geluid is zet lopende functie
delay (100);
}
return lopen; // 0 = niet wachten, > 0 is wachten op einde geluid
}
//===
#if geluidswagon
// GELUID AAN of UIT ZETTEN
// alleen voor geluidswagon
// zet geluids volgnummer variable en slaat deze op.
// geluid 0 = geen geluid, 1-6 is volgnummer van map op MP3 speler
// input: functie nummer.
bool geluidAanUit(int fun) {
bool aanUit = false;
if (geluid) { // geluid staat al aan
if (fun == selecteerGeluidUit) { // functie: geluid uit
speelGeluid (geluid, selecteerGeluidUit); // speel afzet-geluid af
geluid = 0; // geluid gaat straks uit
EEPROM.write(geluidadr,geluid); // onthou dat geluid uit is op EEPROM geheugen
delay (2000); // geluid laten afspelen
aanUit=true;
}
}
else { // geluid is uit
geluid = fun;
if (geluid && aantalSnelheden[geluid-1] > 0) { // er is een definitie voor deze loc (volgnummer)
if (lopendeFunctie == geluid ) { // starten als 2x dezelfde functie is gedetecteerd
EEPROM.write(geluidadr,geluid); // zet gewenste loc aan
speelGeluid (geluid, startgeluid); // speel startgeluid af
delay (1000); // even wachten
aanUit=true;
}
else { // deze functie 1e keer
lopendeFunctie = geluid; // onthou deze functie
geluid = 0;
geluidAanteller = 50;
delay (1000); // functietoets 1 seconde indrukken om geluid te starten
}
} else {
geluid = 0; // geen geluid of definitie
if (geluidAanteller > 0) {
geluidAanteller--;
}
}
}
return aanUit;
}
#endif
// GELUID AFSPELEN
// stuurt commando 'afspelen geluidsbestand' naar de MP3 speler
// input: - nummer van de map op SD kaart (0 = geen geluid)
// - nummer van MP3 bestand
void speelGeluid(int mapnummer, int bestandnummer) {
if (mapnummer) { // geluid staat aan (map > 0 )
execute_CMD(0x0F, mapnummer, bestandnummer);
delay(200);
#if probleemoplosser
Serial.print("Geluidsbestand gestart: ");
Serial.println(bestandnummer);
#endif
}
}
//===
// START MP3 SPELER
// functie start de MP3 speler. Geeft eventueel eerst een reset.
// input: reset y/n
void startMP3(boolean rst) {
#if probleemoplosser
Serial.println("MP3 speler initialisatie");
#endif
if (rst) {
execute_CMD(0x0C, 0, 0); // stuur reset commando
delay (200);
}
execute_CMD(0x3F, 0, 0); // initialiseer MP3 speler
delay (MP3inittijd); // wacht tot initialisatie klaar is
execute_CMD(0x06, 0, volume); // zet het geluidsvolumevolume
delay (80);
execute_CMD(0x07, 0, equalizer); // equalizer
delay (80);
}
//===
// STATUS VAN MP3 SPELER LEZEN
// output: 0 = geen info
// 1 = mp3 klaar (speelt niet)
// 2 = mp3 speelt
// 3 = fout
// 4 = onbekend
int MP3status () {
int m = 4; // standaard: onbekend
int t = 0;
byte b;
int bstat; // status byte
int btrack; // bestand nummer
#if MP3monster
if ( !MP3Serial.available() ) { // nog niets ontvangen
if (MP3count < millis() ) {
execute_CMD (0x42,0,0); // query huidig bestand dat wordt afgespeeld
MP3count = millis() + MP3monster; // volgende MP3 'monster' tijdstip zetten
delay (20);
}
}
#endif
if (MP3Serial.available() > 9) { // er is een bericht op de seriele bus
while(MP3Serial.available()) { // serieel uitlezen
t++;
b = MP3Serial.read();
if (t == 4) { // dit is de status byte
bstat = b;
}
if (t == 7) { // dit is het bestandsnummer
btrack = b;
}
if (t == 10){ // meer dan 1 bericht
t=0;
}
#if probleemoplosser
Serial.print(b,HEX);
Serial.print(".");
#endif
}
#if MP3monster
MP3count = millis() + MP3monster; // volgende MP3 'monster'
#endif
switch (bstat) {
case 0x3F: // initialisatie parameters ontvangen
m = 1; // speler is klaar
break;
case 0x3D: // eind van een bestand
m = 1; // speler is klaar
break;
#if MP3monster
case 0x42: // antwoord op status (monster)
if (btrack > 0) {
m = 2; // bestand speelt
} else {
m = 1; // er speelt geen bestand, speler is kaar
}
break;
#endif
case 0x40: // fout in transmissie
m = 3; // fout
break;
}
#if probleemoplosser
Serial.print("|| MP3 antwoordbyte: ");
Serial.print(bstat,HEX);
Serial.print(" - Bestand#: ");
Serial.print(btrack);
Serial.print(", status: ");
Serial.println(m);
#endif
}
return m;
}
//===
// SERIËLE COMMANDOS VERSTUREN
// Commando's naar MP3 speler versturen
void execute_CMD(byte CMD, byte Par1, byte Par2) // Excecute the command and parameters
{
// Bereken checksum (2 bytes)
int16_t checksum = -(Version_Byte + Command_Length + CMD + Acknowledge + Par1 + Par2);
// Bouw het commando op
byte Command_line[10] = { Start_Byte, Version_Byte, Command_Length, CMD, Acknowledge, Par1, Par2, checksum >> 8, checksum & 0xFF, End_Byte};
// Verstuur commando naar MP3 speler
for (byte k=0; k<10; k++)
{
MP3Serial.write( Command_line[k]);
}
}
//===
// ----- HOOFDPROGRAMMA -----
// ----- initialisatie -----
void setup() {
// versie en configuratie op seriele poort (monitor), alleen voor Arduino
#if Arduino
Serial.begin(9600);
Serial.print("GELUIDSMODULE versie "); Serial.println(versie);
Serial.print("Pin configuratie: rijstroom op digitale pin ");
Serial.print(rijpin[0]); Serial.print(" en "); Serial.print(rijpin[1]);
Serial.print(", serieel tx/rx op pin ");
Serial.print(MP3TX); Serial.print(" en "); Serial.println(MP3RX);
Serial.print("MP3 instellingen: volume = ");
Serial.print(volume); Serial.print(", equalizer = "); Serial.println(equalizer);
Serial.print("MP3 inittijd (ms): "); Serial.print(MP3inittijd); Serial.print(", ");
Serial.print("MP3 bemonstering (ms): "); Serial.println(MP3monster);
Serial.println("-- einde configuratie info --");
// lichtfunctie alleen voor Arduino, niet voor DigiSpark
licht = EEPROM.read(licht1adr); // laatste licht waarde uit EEPROM
pinMode (lichtPin,OUTPUT);
analogWrite (lichtPin,licht); // licht aan of uit: waarde uit EEPROM
#endif
#if uitgebreidLicht // 2e lichtfunctie geïnstalleerd
licht2 = EEPROM.read(licht2adr); // laatste licht waarde uit EEPROM
pinMode (lichtPin2,OUTPUT);
analogWrite (lichtPin2,licht2); // licht aan of uit: waarde uit EEPROM
#endif
// Alleen voor geluidswagon kan geluid worden aan en uitgezet.
#if geluidswagon
geluid = constrain (EEPROM.read(geluidadr), 0, 6); // laatste geluid waarde uit EEPROM (0 = geen geluid)
if (geluid && aantalSnelheden [geluid - 1] == 0) { // geen juiste waarde (bijvoorbeeld eerste opstart)
geluid = 1; // zet bij ongeldige waarde het geluid volgnummer op "1".
EEPROM.write (geluidadr,1);
}
#endif
// intialiseren pinnen en MP3speler
pinMode (rijpin[0],INPUT);
digitalWrite(rijpin[0],pullup);
pinMode (rijpin[1],INPUT);
digitalWrite(rijpin[1],pullup);
delay (200);
// geluidsmodule starten
MP3Serial.begin(9600); // start seriele communicatie met MP3 speler
startMP3(false); // intialiseren volume en equaliser
#if (!geluidswagon)
while (MP3status() != 1) { // wacht op bericht dat initialisatie klaar is
}
#endif
speelGeluid (geluid, startgeluid); // speel startgeluid af
}
// ----- hoofdlus ------
void loop() {
// Pulsbreedte bepalen
do {
vooruit = !vooruit; // wissel de pin waarop de rijstroom wordt gemeten
meetPuls();
#if Arduino
} while (pulsPeriode > rijPeriode + pulsruis || pulsbreedteHoog < minhoog || pulsbreedteLaag < pulsruis); // Arduino meet soms enig "laag" op passieve pin
#else
} while (pulsbreedteHoog < minhoog); // 'hoog' signaal alleen op actieve rijpin
#endif
//----
MP3speler = MP3status();
switch (MP3speler) {
case 1: // bestand klaar (MP3 speelt niet)
lopendeFunctie = 0; // er loopt dan geen speciale functie meer
speelGeluid(geluid, snelheid + stationair); // geluidsbestand vanaf stationair / stilstand
vorigeSnelheid = snelheid;
break;
case 3: // fout
startMP3(true); // reset MP3 speler
lopendeFunctie = 0;
while (MP3status() != 1) { // wacht op bericht dat initialisatie klaar is
}
break;
default:
// MP3 speler speelt of er is geen info.
// alleen een geluid starten bij:
// - starten van een speciale functie
// - snelheidswissel als er geen speciale functie loopt
// - en het geluid aan stat (kan bij geluidswagon worden uitgezet)
functie = getFunctie();
// speciale geluidsfunctie gevonden
if (functie) { // functie toets ingedrukt
// als speciale functie is gevonden, controleer de functie frequentie nogmaals.
// Hiermee wordt onterecht starten van functie voorkomen (door bijvoorbeeld storing op de stroomopname).
delay (5);
meetPuls();
if (functie == getFunctie()) {
// * Lichtfunctie
#if (!DigiSpark) // DigiSpark geen lichtfunctie
if (functie == lichtfunctie) {
if (licht == 0) {licht = lichtsterkte;} else { licht = 0;} // wissel licht aan/uit op juiste sterkte
analogWrite(lichtPin, licht); // zet licht aan (op dimwaarde) of uit
EEPROM.write(licht1adr,licht); // onthou licht aan of uit tot volgende opstart.
delay (100);
}
#endif
#if (uitgebreidLicht) // 2e lichtfunctie
if (functie == lichtfunctie2) {
if (licht2 == 0) {licht2 = lichtsterkte2;} else { licht2 = 0;} // wissel 2e licht aan/uit op juiste sterkte
analogWrite(lichtPin2, licht2); // zet licht aan (op dimwaarde) of uit
EEPROM.write(licht2adr,licht2); // onthou licht aan of uit tot volgende opstart.
delay (100);
}
#endif
// * Geluidsfuncties
#if !geluidswagon
lopendeFunctie = startFunctie(functie); // start het geluid
#else
if (geluidAanUit(functie)){ // geluidswagon kan geluid aan- en uitzetten
lopendeFunctie = 0;
}
else { // gewoon geluid alleen starten als geluid al aan was en blijft
if (geluid){
lopendeFunctie = startFunctie(functie); // start het gewone geluid
}
}
#endif
}
}
// rijgeluid (of stationair)
pulsbreedte = 100 * pulsbreedteHoog / pulsPeriode;
#if geluidswagon
if (geluid && pulsbreedte > pulsbreedtestil[geluid-1]) {
if (pulsbreedte > pulsbreedtemax[geluid-1]) {
pulsbreedte = pulsbreedtemax[geluid-1];
}
// geluidsbestand berekenen: reken pulssbreedte % om naar geluidsbestand volgnummer
snelheid = map(100 * sqrt (10+pulsbreedte-pulsbreedtestil[geluid-1]), sqrtpbstil, sqrtpbmax[geluid-1], 0, aantalSnelheden[geluid-1]);
#else
if (pulsbreedte > pulsbreedtestil) {
if (pulsbreedte > pulsbreedtemax) {
pulsbreedte = pulsbreedtemax;
}
// geluidsbestand berekenen: reken pulssbreedte % om naar geluidsbestand volgnummer
snelheid = map(100 * sqrt (10+pulsbreedte-pulsbreedtestil), sqrtpbstil, sqrtpbmax, 0, aantalSnelheden); // reken pulssbreedte % om naar geluidsbestand
#endif
if (vorigeSnelheid != snelheid && !lopendeFunctie) { // snelheidswissel bij lopend geluid en geen speciale functie bezig
speelGeluid(geluid, snelheid + stationair); // rijgeluid: geluidsbestand vanaf stationair / stilstand
vorigeSnelheid = snelheid;
}
}
} // einde case switch
}
/*
* MODELTREIN LICHTMODULE
* Schakelbaar licht voor de modeltrein, voor binneverlichting, sluitverlichting en meer.
*
* Rijstroom met pulsbreedtebesturing is nodig: met veranderingen van de pulsfrequentie worden
* de lichtfuncties bestuurd.
*
* versie 0.2 - 19 sep 2018
*
* Notities:
* voor Digispark EEPROM gebruik moet de library worden gekopieerd van
* C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM\
* naar
* C:\Users\{user.name}\AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.5\libraries\EEPROM\
*
* Voor gebruik losse ATtiny: Bootloader branden met BOD op 4.3V en clock op 16 MHz
*/
// --- DEFINITIES ----
// Pinnen
#define lichtPin 0 // pin1 voor aansturen van licht: PWM pin (dimbaar licht)
#define lichtPin2 1 // 2e lichtpin
#define rijPin1 3 // rijstroom meting
#define rijPin2 4 // rijstroom meting
// definities voor licht
#define lichtfunctie 5 // functie 5 is sluitlicht aan/uit
#define lichtsterkte 20 // lichtsterkte (0-255)
#define lichtfunctie2 6 // functie 6 is binnenverlichting aan/uit
#define lichtsterkte2 50 // lichtsterkte (0-255)
// EEPROM geheugenlocaties
#define licht1adr 0
#define licht2adr 1
// definities voor de meting van de rijstroom
#define pullup false // geeft aan of de interne pullup weerstand gebruikt moet worden
#define maxpulsperiode 5000 // hoe lang wachten (minimaal 2x periode rijstroom PWM)
// Frequenties (Periodes) op de rijstroom
#define rijPeriode 2020 // rijstroom puls in us
#define functie_01_Periode 1500 // Periode (freq.) functie 1 - niet gebruikt (geluid)
#define functie_02_Periode 1250 // Periode (freq.) functie 2 - niet gebruikt (geluid)
#define functie_03_Periode 990 // Periode (freq.) functie 3 - niet gebruikt (geluid)
#define functie_04_Periode 790 // Periode (freq.) functie 4 - niet gebruikt (geluid)
#define functie_05_Periode 590 // Periode (freq.) functie 5 - licht 1
#define functie_06_Periode 450 // Periode (freq.) functie 6 - licht 2
#define pulsruis 70 // maximaal verschil in gemeten Periodes (ruis)
#define minhoog 100 // minimaal "hoog" signaal
// ---- libraries en objecten ----
#include <EEPROM.h> // EEPROM om licht aan/uit en geluid aan/uit te onthouden
// --- CONSTANTES EN VARIABELEN---
// rijstroom variabelen
int rijpin[] {rijPin1, rijPin2};
int vooruit = 1; // richting: bepaalt welke pin wordt uitgelezen voor de rijstroom puls
double pulsbreedteHoog;
double pulsbreedteLaag;
double pulsPeriode;
// variabelen voor speciale functies op de rijstroom
int functie = 0; // speciale functie frequentie gemeten
int licht; // licht sterkte of uit (0);
int licht2; // licht sterkte of uit (0);
// --- FUNCTIES ---
// MEET DE PULS OP DE RiJSTROOM
void meetPuls() {
// puls meting variabelen: lengte 'hoog', 'laag' en trillingstijd (periode). Alle tijden in us.
pulsbreedteHoog = pulseIn(rijpin[vooruit], HIGH, maxpulsperiode);
pulsbreedteLaag = pulseIn(rijpin[vooruit], LOW, maxpulsperiode );
pulsPeriode = pulsbreedteHoog + pulsbreedteLaag;
}
// HERKEN FUNCTIE-FREQUENTIE
// functie voor het checken van functie-frequenties
// op de puls (functietoets).
int getFunctie () {
int f = 0;
if (abs (pulsPeriode - functie_01_Periode) < pulsruis) { f = 1;}
if (abs (pulsPeriode - functie_02_Periode) < pulsruis) { f = 2;}
if (abs (pulsPeriode - functie_03_Periode) < pulsruis) { f = 3;}
if (abs (pulsPeriode - functie_04_Periode) < pulsruis) { f = 4;}
if (abs (pulsPeriode - functie_05_Periode) < pulsruis) { f = 5;}
if (abs (pulsPeriode - functie_06_Periode) < pulsruis) { f = 6;}
return f;
}
// ----- HOOFDPROGRAMMA -----
// ----- initialisatie -----
void setup() {
// intialiseren rij pinnen
pinMode (rijpin[0],INPUT);
digitalWrite(rijpin[0],pullup);
pinMode (rijpin[1],INPUT);
digitalWrite(rijpin[1],pullup);
delay(100); // even wachten op opladen elco (stabiele voeding)
// bij opstarten de opgeslagen licht status gebruiken
licht = EEPROM.read(licht1adr); // laatste licht waarde uit EEPROM
pinMode (lichtPin,OUTPUT);
analogWrite (lichtPin,licht); // licht aan of uit: waarde uit EEPROM
licht2 = EEPROM.read(licht2adr); // laatste licht waarde uit EEPROM
pinMode (lichtPin2,OUTPUT);
analogWrite (lichtPin2,licht2); // licht aan of uit: waarde uit EEPROM
}
// ----- hoofdlus ------
void loop() {
// Pulsbreedte bepalen
do {
vooruit = !vooruit; // wissel de pin waarop de rijstroom wordt gemeten
meetPuls();
} while (pulsbreedteHoog < minhoog || pulsbreedteLaag < pulsruis); // 'hoog' signaal alleen op actieve rijpin
functie = getFunctie();
// speciale geluidsfunctie gevonden
if (functie) {
// als speciale functie is gevonden, controleer de functie frequentie nogmaals.
// Hiermee wordt onterecht meten voorkomen (door bijvoorbeeld storing op de stroomopname).
delay (5); // korte pauze tussen de metingen
meetPuls();
if (functie == getFunctie()) { // nog steeds dezelfde funtie op de rijstroom
switch (functie) {
case lichtfunctie:
if (licht == 0) {licht = lichtsterkte;} else { licht = 0;} // wissel licht aan/uit op juiste sterkte
analogWrite(lichtPin, licht); // zet licht aan (op dimwaarde) of uit
EEPROM.write(licht1adr,licht); // onthou licht aan of uit tot volgende opstart.
delay (500);
break;
case lichtfunctie2:
if (licht2 == 0) {licht2 = lichtsterkte2;} else { licht2 = 0;} // wissel 2e licht aan/uit op juiste sterkte
analogWrite(lichtPin2, licht2); // zet licht aan (op dimwaarde) of uit
EEPROM.write(licht2adr,licht2); // onthou licht aan of uit tot volgende opstart.
delay (500);
break;
}
}
}
}
Wauw Rob ... ik schiet ineens ook weer wakker. :o Misschien is dat ook wel wat voor mij. Ik laat je eerst de moeilijkheden oplossen en dan maak ik daar misschien graag weer gebruik van. ;DJe had inderdaad ook nog wat dieseltjes. Verstandig, hoor, om gewoon even af te wachten :-X
/*
* DIESEL GELUIDSMODULE
* Werkt met eigen PWM (rond 10 kHz) voor 7 staps speaker volume.
* Golfvorm wordt gedefinieeerd in array, met stappen van 4: waardes van 0 t/m 24
*
* Versie 1.0, 25 november 2018 - Rob van Deursen
*/
// --- DEFINITIES ----
// kies de loc om te compileren: zet precies één definitie op 'true'
#define V60 true // @ ATtiny (los). Bootloader branden met BOD op 2.7V en clock op 16 MHz
#if V60
#define ATtiny true // V60 @ ATtiny
#define ruisPin 0 // pin voor aansturen van speaker
#define rijPin1 1 // rijstroom meting
#define rijPin2 4 // rijstroom meting
#define statGolf 83 // aantal stappen in stationaire golf (-1)
#define statStap 5500 // us per golf stap (stationair)
#define rijdGolf72 71 // aantal stappen bij rijden golf (-1)
#define rijdGolf60 59 // aantal stappen bij rijden golf (-1)
#define rijdGolf54 53 // aantal stappen bij rijden golf (-1)
#define rijdGolf48 47 // aantal stappen bij rijden golf (-1)
#define rijdStap 5500 // us per golf stap (rijden)
// berekening snelheid
#define pulsbreedtestil 30 // pulsbreedte in % waaronder loc stil staat / stationair geluid
#endif
// definities voor de meting van de rijstroom
#define pullup false // geeft aan of de interne pullup weerstand gebruikt moet worden
#define maxpulsperiode 2750 // hoe lang wachten (minimaal 2x periode rijstroom PWM)
// Frequenties (Periodes) op de rijstroom
#define rijPeriode 2020 // rijstroom puls in us
#if ATtiny
// #define functie_01_Periode 1350 // Periode (freq.) functie 1
#define functie_01_Periode 1400 // Periode (freq.) functie 1
#define functie_02_Periode 1190 // Periode (freq.) functie 2
#else
#define functie_01_Periode 1500 // Periode (freq.) functie 1
#define functie_02_Periode 1250 // Periode (freq.) functie 2
#endif
#define functie_03_Periode 990 // Periode (freq.) functie 3
#define functie_04_Periode 790 // Periode (freq.) functie 4
#define functie_05_Periode 590 // Periode (freq.) functie 5 - niet gebruikt
#define functie_06_Periode 450 // Periode (freq.) functie 6 - niet gebruikt
#define pulsruis 80 // maximaal verschil in gemeten Periodes (ruis)
#define minhoog 100 // minimaal "hoog" signaal
#define pulsbreedteStap 3.0 // verschil in pulsbreedte om op- of terug te schakelen met rijgeluid
// --- VARIABELEN ---
// rijstroom variabelen
int rijpin[] {rijPin1, rijPin2};
int vooruit = 1; // richting: bepaalt welke pin wordt uitgelezen voor de rijstroom puls
double pulsbreedteHoog;
double pulsbreedteLaag;
double pulsPeriode;
float pulsbreedte = 0; // pulsbreedte in %
int functie = 0; // speciale functie frequentie gemeten
float vorigePulsbreedte = 30; // laatste pulsbreedte - wordt gebruikt om motorgeluid te regelen.
int pbv = 0; // pulsbreedteverschil
// reeksen voor geluidsgolven
// Starten:
byte dieselStrt84 [] { 0, 0, 16, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 24, 0, 0, 0, 0, 0, 0, 12, 8, 4, 0, 0, 0, 8, 12, 16, 20, 0, 0, 0, 24, 12, 16, 4, 0, 4, 0, 0, 8, 24, 0, 0, 0, 8, 0, 24, 12, 4, 0, 0, 4, 8, 20, 24, 0, 0, 0, 0, 0, 20, 12, 4, 0, 0, 8, 0, 12, 20, 24, 12, 0, 0, 20, 12, 0, 0 };
// golf# 1 2 3 4 5 6 7 8 9 10 11 12
// Stationair:
byte dieselStat84 [] { 0, 0, 12, 24, 12, 24, 0, 0, 0, 24, 24, 8, 4, 0, 0, 4, 12, 0, 16, 24, 0, 0, 16, 24, 12, 8, 4, 0, 0, 0, 8, 4, 8, 12, 0, 0, 0, 16, 8, 12, 4, 0, 4, 0, 0, 8, 16, 0, 0, 0, 4, 0, 16, 12, 4, 0, 0, 4, 8, 4, 16, 0, 0, 0, 0, 0, 12, 8, 4, 0, 0, 4, 0, 8, 12, 16, 12, 0, 0, 16, 8, 0, 0 };
// golf# 1 2 3 4 5 6 7 8 9 10 11 12
// Rijden:
byte dieselRijd72 [] { 0, 4, 8, 12, 24, 0, 0, 24, 16, 8, 4, 0, 0, 4, 12, 16, 24, 0, 0, 24, 20, 12, 8, 0, 0, 8, 12, 20, 24, 0, 0, 24, 16, 12, 4, 0, 0, 8, 16, 20, 24, 0, 0, 24, 16, 12, 4, 0, 0, 8, 12, 16, 24, 0, 0, 24, 20, 12, 4, 0, 0, 4, 12, 20, 24, 0, 0, 24, 20, 12, 8, 0 };
byte dieselRijd54 [] { 0, 0, 12, 24, 0, 24, 16, 0, 0, 0, 0, 16, 24, 0, 24, 20, 0, 0, 0, 8, 20, 24, 0, 24, 16, 0, 0, 0, 4, 20, 24, 0, 24, 16, 0, 0, 0, 0, 16, 24, 0, 24, 20, 0, 0, 0, 4, 20, 24, 0, 24, 20, 0, 0 };
// golf# 1 2 3 4 5 6 7 8 9 10 11 12
// Niet gebruikte golfvormen voor rijden:
//byte dieselRijd60 [] { 0, 0, 0, 12, 24, 0, 24, 16, 0, 0, 0, 0, 0, 16, 24, 0, 24, 20, 0, 0, 0, 0, 8, 20, 24, 0, 24, 16, 0, 0, 0, 0, 4, 20, 24, 0, 24, 16, 0, 0, 0, 0, 0, 16, 24, 0, 24, 20, 0, 0, 0, 0, 4, 20, 24, 0, 24, 20, 0, 0 };
//byte dieselRijd48 [] { 0, 0, 12, 24, 0, 24, 16, 0, 0, 0, 16, 24, 0, 24, 20, 0, 0, 8, 20, 24, 0, 24, 16, 0, 0, 0, 16, 24, 0, 24, 16, 0, 0, 0, 12, 24, 0, 24, 20, 0, 0, 0, 16, 24, 0, 24, 12, 0 };
// Hoorn (vol volume, half volume):
byte hoorn [] { 12, 4, 12, 24, 16, 12, 24, 0};
byte hoorn2[] { 8, 0, 8, 16, 12, 8, 16, 0};
// overige variablen
int t = 0; // index geluidsreeks (array)
int gs; // waarde geluidsstap
int d = statStap; // vertraging afspelen geluidswaarden (us)
bool stationair = true;
bool gas = false;
unsigned long u; // microseconden
unsigned long m; // milliseconden
// --- FUNCTIES ---
// PULSBREEDTE 0-24, ROND 10 kHz
// in stappen van 4. Voor afspelen van geluidsgolven.
// na het verloop van de gewensde tijdsfuur staat de PWM uit.
// input: pin waarop PWM wordt gezet
// waarde van PWM , 7 stappen van 0-24 (0 = uit, 24 = maximaal)
// tijdsduur van PWM waarde (in us)
void microPWM (int pin,int pwm, int tim) {
unsigned long mics = micros() + tim;
do {
digitalWrite (pin,HIGH);
delayMicroseconds (pwm);
digitalWrite (pin,LOW);
delayMicroseconds (24-pwm);
} while (micros() <= mics);
}
// SPEEL GELUIDSGOLF AF
// input: reeks voor golfvorm
// aantal stappen in de golfvorm reeks
// tijdsduur van elke stap in us
// aantal herhalingen
void speelGolf (byte golf[], int stappen, int usec, int herhaal){
int g;
unsigned long w;
//int us = usec;
for (int y = 0; y < herhaal ; y++){
for (int x = 0; x < stappen ; x++) {
g = golf[x];
microPWM(ruisPin, g , usec);
}
}
}
// MEET DE PULS OP DE RIJSTROOM
void meetPuls() {
// puls meting variabelen: lengte 'hoog', 'laag' en trillingstijd (periode). Alle tijden in us.
pulsbreedteHoog = pulseIn(rijpin[vooruit], HIGH, maxpulsperiode);
pulsbreedteLaag = pulseIn(rijpin[vooruit], LOW, maxpulsperiode );
pulsPeriode = pulsbreedteHoog + pulsbreedteLaag;
}
// HERKEN FUNCTIE-FREQUENTIE OP DE RIJSTROOM
// functie voor het checken van functie-frequenties
// op de puls (functietoets).
int getFunctie () {
int f = 0;
if (abs (pulsPeriode - functie_01_Periode) < pulsruis) { f = 1;}
if (abs (pulsPeriode - functie_02_Periode) < pulsruis) { f = 2;}
if (abs (pulsPeriode - functie_03_Periode) < pulsruis) { f = 3;}
if (abs (pulsPeriode - functie_04_Periode) < pulsruis) { f = 4;}
return f;
}
// FUNCTIE: WACHTEN EN TERWIJL RIJSTROOM METEN
int wachtEnMeet() {
int fu = 0;
u = micros() + d;
d = random (rijdStap, rijdStap+300);
vooruit = !vooruit; // wissel de pin waarop de rijstroom wordt gemeten
meetPuls();
if (pulsbreedteHoog > minhoog && pulsbreedteLaag > pulsruis) {
pulsbreedte = 100 * pulsbreedteHoog / pulsPeriode;
stationair = (pulsbreedte <= pulsbreedtestil); // stationair / rijden
fu = getFunctie();
}
while (micros() < u) {
;
}
return fu;
}
// SPEEL GELUIDSFUCTIE
// input: nummer van de geluidsfunctie
void speelFunctie(int gf) {
switch (gf) {
case 1:
// lange hoorn
speelGolf (hoorn2, 8, 300, 20 );
speelGolf (hoorn , 8, 300, 540);
speelGolf (hoorn2, 8, 308, 50 );
break;
case 2:
// korte hoorn
speelGolf (hoorn2, 8, 300, 20 );
speelGolf (hoorn , 8, 300, 150);
speelGolf (hoorn2, 8, 308, 50 );
break;
case 3:
// remgeluid: 2,4 seconde
m = millis() +2400;
while (millis() < m) {
microPWM (ruisPin, 12*random (0,2), random (4, 33));
delayMicroseconds (190 + random (65));
}
break;
case 4:
// motor afzetten
speelGolf (dieselStrt84, 83, 5200, 1);
speelGolf (dieselStrt84, 83, 6900, 1);
speelGolf (dieselStrt84, 27, 8300, 3);
speelGolf (dieselStrt84, 27, 9500, 1);
delay (5000);
break;
}
}
// --- INITIALISATIE ---
// Achtereenvolgens wordt het volgende uitgevoerd:
// Alle pinnen goed zetten (input, output)
// motor starten als de loc nog niet rijdt.
void setup() {
// Pinnen initialiseren
pinMode ( ruisPin, OUTPUT);
digitalWrite (ruisPin, LOW);
pinMode (rijpin[0],INPUT);
digitalWrite (rijpin[0],pullup);
pinMode (rijpin[1],INPUT);
digitalWrite (rijpin[1],pullup);
delay(150);
//meet de rijstroom op beide pinnen om te kijken of er gereden wordt
for (t=0; t < 4; t++) {
meetPuls();
if (pulsbreedteHoog > minhoog && pulsbreedteLaag > pulsruis) {
pulsbreedte = 100 * pulsbreedteHoog / pulsPeriode;
stationair = (pulsbreedte <= pulsbreedtestil); // stationair / rijden
}
vooruit = !vooruit; // wissel de pin waarop de rijstroom wordt gemeten
}
if (stationair) {
//Loc staat stil: start de motor
speelGolf (dieselStrt84, 27, 8300, 5);
speelGolf (dieselStrt84, 83, 6700, 1);
speelGolf (dieselStrt84, 83, 5200, 1);
}
}
// --- HOOFPROGRAMMA ---
// Het hoofdprogramma speelt het motor geluid af, stationair of rijden.
// Tussendoor wordt de rijstroom gemeten voor snelheidswisseling en
// speciale geluidsfuncties.
// Het geluid wisselt tussen stationair en rijden, afhankelijk van de rijstroom
// als een geluidsfunctie wordt geregistreerd, wordt die ook afgespeeld.
void loop() {
if (stationair) {
// stationar geluid
gas = false;
vorigePulsbreedte = pulsbreedtestil;
for (t = 0; t < statGolf ; t++) {
gs = dieselStat84[t];
if (gs) {
microPWM(ruisPin, gs , d);
}
else {
functie = wachtEnMeet();
// bij stilstand 1x functie meten. Minder contact storingen
if (functie) {
speelFunctie(functie) ;
}
}
}
}
if (!stationair) {
// geluid bij rijden: in 2 trappen
pbv = pulsbreedte - vorigePulsbreedte;
if (pbv > pulsbreedteStap) {
gas = true;
vorigePulsbreedte = pulsbreedte;
}
if (pbv < -pulsbreedteStap) {
gas = false;
vorigePulsbreedte = pulsbreedte;
}
if (!gas) {
for (t = 0; t < rijdGolf72 ; t++) {
gs = dieselRijd72[t];
if (gs) {
microPWM(ruisPin, gs , d);
}
else {
if (wachtEnMeet() ) {
// bij rijden 2x functie meten om contactstoringen te vermijden
meetPuls();
if (pulsbreedteHoog > minhoog && pulsbreedteLaag > pulsruis) {
functie = getFunctie();
}
if (functie) {
speelFunctie(functie) ;
}
}
}
}
}
else {
for (t = 0; t < rijdGolf54 ; t++) {
gs = dieselRijd54[t];
if (gs) {
microPWM(ruisPin, gs , d);
}
else {
if (wachtEnMeet() ) {
// bij rijden 2x functie meten om contactstoringen te vermijden
meetPuls();
if (pulsbreedteHoog > minhoog && pulsbreedteLaag > pulsruis) {
functie = getFunctie();
}
if (functie) {
speelFunctie(functie) ;
}
}
}
}
}
}
}
Is het schema hetzelfde als voor de stomers?Yep, dezelfde hardware als voor de stomers. Let alleen even op de gebruikte pinnen: ik wissel ze nog wel eens afhankelijk van wat het beste past. Maar die definieer je hier:
#define ruisPin 0 // pin voor aansturen van speaker
#define rijPin1 1 // rijstroom meting
#define rijPin2 4 // rijstroom meting
Mocht je ooit een dieseltje doen, dan moeten nog wel de extra geluidsfuncties uit deze sketch worden weggehaald. Anders loop je de kans dat bij jouw rijstroomregeling het gewone rijden niet werkt. Maar dat is simpel te doen, hoor: heb ik bij de sketch voor je stomers ook gedaan ;DNou heb ik een stationair geluidsbron die rijspanning afhankelijk het stoomlokgeluid afspeelt.wel een idee.
Dit moet toch ook mogelijk zijn m.b.v. een Arduino met mp3?
En dan wellicht verschillende mp3 stoomlok geluiden zodat je het “juiste” geluid kunt afspelen bij de loc.
Zou er ook iets van dit systeem werken voor DCC?
Gezien de prijs is dat namelijk wel intressant :-)
Volgens mij ben jij de enige die het forum op dit moment leven in blijft blazen. Je gaat maar door man. Verder laten we het allemaal afweten.
Verkrijgbaar!:
2 LED's in één behuizing, ZONDER een gezamenlijke anode.
(https://myalbum.com/photo/8iaCF3VNMAi8/1k0.jpg)
Op Ebay te vinden onder:
https://www.ebay.nl/itm/Bicolor-LED-2mm-3mm-or-5mm-color-red-white-red-warm-white-or-red-yellow/190894964341?hash=item2c7239fe75:g:wuYAAOxytL9SI4ha:rk:1:pf:0 (https://www.ebay.nl/itm/Bicolor-LED-2mm-3mm-or-5mm-color-red-white-red-warm-white-or-red-yellow/190894964341?hash=item2c7239fe75:g:wuYAAOxytL9SI4ha:rk:1:pf:0)
Gr.Piet
Tip van de week. Want het werkt op de beweging van de loc of wagen waar je de soundchip inbouwt. Ik wil er zelf binnenkort ook één aanschaffen!
Ik denk dat de BR53 "gewone" cilinders heeft, gewoon betekent dat de druk van de ketel in één keer naar de schoorsteen gaat, dit in tegenstelling tot een "expansie" systeem waar de druk in meer dan één fase naar de schoorsteen gaat.Zo is het. Je hebt eigenlijk 2 locomotieven met 1 gezamenlijke ketel :)
Dat de BR 96 achter hoge druk had en voor lage druk, moet ik eens bestuderen, het geeft wat problemen als de cilinders voor net geen stoom nodig hebben en de cilinders achter juist stoom kwijt moeten.Volgens Wikipedia is de stoomtoevoer naar beide cilindergroepen ook direct vanuit de ketel te doen als dat nodig is. Dat maakte de bediening van deze locomotieven een stuk ingewikkelder, maar wegens dubbel gebruik van de stoom tijdens de 'normale' loop wel merkbaar efficiënter.
Voor het eerst van mijn leven een gelede locomotief gezien...en dat was door de foto's in de post hierboven. :-)Tsja, Peter. In Europa waren gelede locs niet zo populair. De Amerikanen bouwden enorme gelede locs. Zelfs een versie met 3 drijfwerken....
Beste Rob,… die zoek ik ook, maar lastig te vinden inderdaad.
Daarom zocht ik ook naar een tekening of beschrijving van het stoomsysteem......, wij hebben hetzelfde idee....
Groet, Anne W
Hoe staat het eigenlijk met jouw railbus ombouw?
Heb je dan de sound gemixt zodat rechts iets anders klinkt dan links?Ja: 2 motoren die na elkaar starten (of stopgezet worden), elk op een kanaal. De ene motor loopt ook net iets sneller (5%) dan de andere.
Nou heb ik een vraagje. Is het niet mogelijk het geluid van één van de luidsprekertjes iets te vertragen? Dan lijkt het misschien ook of er twee motoren draaien. Ik denk nu even hardop hè ... Geen flauw idee of dat kan.Ik heb geen idee. Er is vast wel wat elektronica die dat kan. Lekker hardop blijven meedenken, Pierre!
Ja Rob ... twee spelertjes is natuurlijk nog beter. Dan gaat net als in het echt het toerental wel gelijk omhoog maar de slag van de zuigers niet helemaal synchroon. Dat lijkt me de mooiste oplossing. ;)Dit is precies wat ik eerst probeer te bereiken met de dubbel mono.... De geluidsbestanden zijn als zo gemaakt, dus dit is al enigszins te horen...
Is in dat rijdende stereootje geen dopplereffect in te bouwen?Nu kan deze Lima loc behoorlijk snel, ik zal straks eens luisteren.... :o
is er een reden dat je de "analoge" ingangen van de Arduino gebruikt voor de functietoetsen en niet de digitale?Nee, hoor, alleen esthetische: zo zitten alle 'input' pinnen mooi naast elkaar.
Mijn idee is om een lage frequentie te gebruiken voor langzaam rijden en een hogere voor hoge(re) snelheden.Dat is zeker te programmeren, je kunt bijvoorbeeld de 'deler' van de klok voor de PWM aanpassen (al heb ik dat zelf nog niet gedaan), al zijn er ook andere manieren.
Dat moet in de code voor de Arduino te programeren zijn.
Wat me in je filmpje van "Geluid 3.0" opviel is dat de twee locs onafhankelijk van elkaar rijden op hetzelfde baanvak. Heb ik iets gemist in dit draadje mbt aansturen van de locs op hetzelfde baanvak?Ha, goed gezien. Je hebt niets gemist, hoor. Het is ouderwetse analoge techniek: dit spoor (spoor 2 op het vernieuwde station "Grauberg") heeft 3 vakken die van elkaar elektrisch geïsoleerd zijn en afzonderlijk zijn in- en uit te schakelen. Dat geeft dan operationele mogelijkheden hier met de waterkraan en de verbinding naar spoor 3.
Leuk dat je het analoge materieel weer "uit de mottenballen gaat halen".De ATF truc ken ik inderdaad. Werkt goed.
Rijden met PWM geeft al meteen betere rijeigenschappen, juist ook goed merkbaar met wat ouder soul. Rails goed schoonmaken en een beetje ATF er op (http://www.h0modelspoor.nl/index.php?topic=3121 (http://www.h0modelspoor.nl/index.php?topic=3121)), en dan rijdt ook oud materieel goed.
Dat is zeker te programmeren, je kunt bijvoorbeeld de 'deler' van de klok voor de PWM aanpassen (al heb ik dat zelf nog niet gedaan), al zijn er ook andere manieren.Ik heb begrepen dat een loc bij een lagere frequetie beter langzaam rijdt en dat voor hogere snelheden, een hogere frequentie beter is. De Weistra methode.
Maar waarom zou je een andere frequentie PWM doen bij lagere dan bij hogere snelheid?
Ik heb begrepen dat een loc bij een lagere frequentie beter langzaam rijdt en dat voor hogere snelheden, een hogere frequentie beter is. De Weistra methode.Dat had ik even gemist, maar interessant.
Rein noemde dit ook al, enkele berichten hierboven.
Code voor het instellen van D3 & D11:
TCCR2B = TCCR2B & B11111000 | B00000001; // for PWM frequency of 31372.55 Hz
TCCR2B = TCCR2B & B11111000 | B00000010; // for PWM frequency of 3921.16 Hz
TCCR2B = TCCR2B & B11111000 | B00000011; // for PWM frequency of 980.39 Hz
TCCR2B = TCCR2B & B11111000 | B00000100; // for PWM frequency of 490.20 Hz (The DEFAULT)
TCCR2B = TCCR2B & B11111000 | B00000101; // for PWM frequency of 245.10 Hz
TCCR2B = TCCR2B & B11111000 | B00000110; // for PWM frequency of 122.55 Hz
TCCR2B = TCCR2B & B11111000 | B00000111; // for PWM frequency of 30.64 Hz
Code voor het instellen van D5 & D6:
TCCR0B = TCCR0B & B11111000 | B00000001; // for PWM frequency of 62500.00 Hz
TCCR0B = TCCR0B & B11111000 | B00000010; // for PWM frequency of 7812.50 Hz
TCCR0B = TCCR0B & B11111000 | B00000011; // for PWM frequency of 976.56 Hz (The DEFAULT)
TCCR0B = TCCR0B & B11111000 | B00000100; // for PWM frequency of 244.14 Hz
TCCR0B = TCCR0B & B11111000 | B00000101; // for PWM frequency of 61.04 Hz
Code voor het instellen van D9 & D10:
TCCR1B = TCCR1B & B11111000 | B00000001; // set timer 1 divisor to 1 for PWM frequency of 31372.55 Hz
TCCR1B = TCCR1B & B11111000 | B00000010; // for PWM frequency of 3921.16 Hz
TCCR1B = TCCR1B & B11111000 | B00000011; // for PWM frequency of 490.20 Hz (The DEFAULT)
TCCR1B = TCCR1B & B11111000 | B00000100; // for PWM frequency of 122.55 Hz
TCCR1B = TCCR1B & B11111000 | B00000101; // for PWM frequency of 30.64 Hz
Lagere PWM frequentie kan vrij eenvoudig op de Arduino worden ingesteld door de 'deelfactor' met de timers aan te passen. Dan kom je op zijn laagst tot 30 Hz.Code: [Selecteer]Code voor het instellen van D3 & D11:
TCCR2B = TCCR2B & B11111000 | B00000001; // for PWM frequency of 31372.55 Hz
TCCR2B = TCCR2B & B11111000 | B00000010; // for PWM frequency of 3921.16 Hz
TCCR2B = TCCR2B & B11111000 | B00000011; // for PWM frequency of 980.39 Hz
TCCR2B = TCCR2B & B11111000 | B00000100; // for PWM frequency of 490.20 Hz (The DEFAULT)
TCCR2B = TCCR2B & B11111000 | B00000101; // for PWM frequency of 245.10 Hz
TCCR2B = TCCR2B & B11111000 | B00000110; // for PWM frequency of 122.55 Hz
TCCR2B = TCCR2B & B11111000 | B00000111; // for PWM frequency of 30.64 Hz
Code voor het instellen van D5 & D6:
TCCR0B = TCCR0B & B11111000 | B00000001; // for PWM frequency of 62500.00 Hz
TCCR0B = TCCR0B & B11111000 | B00000010; // for PWM frequency of 7812.50 Hz
TCCR0B = TCCR0B & B11111000 | B00000011; // for PWM frequency of 976.56 Hz (The DEFAULT)
TCCR0B = TCCR0B & B11111000 | B00000100; // for PWM frequency of 244.14 Hz
TCCR0B = TCCR0B & B11111000 | B00000101; // for PWM frequency of 61.04 Hz
Code voor het instellen van D9 & D10:
TCCR1B = TCCR1B & B11111000 | B00000001; // set timer 1 divisor to 1 for PWM frequency of 31372.55 Hz
TCCR1B = TCCR1B & B11111000 | B00000010; // for PWM frequency of 3921.16 Hz
TCCR1B = TCCR1B & B11111000 | B00000011; // for PWM frequency of 490.20 Hz (The DEFAULT)
TCCR1B = TCCR1B & B11111000 | B00000100; // for PWM frequency of 122.55 Hz
TCCR1B = TCCR1B & B11111000 | B00000101; // for PWM frequency of 30.64 Hz
Ik heb het geprobeerd, en je kunt inderdaad op 30Hz nog wat langzamer kruipen dan op zo'n 490 Hz, lijkt het.
Maar mijn geluidsmodules trekken het niet. Dus ik hou het maar op de standaard 490Hz. Daar zijn m'n Elco's aan boord op afgestemd.
Maar weer wat geleerd :)
Als je alleen licht doet, is deze lage frequentie bij lage snelheden zeker een optie. En dan kun je bij stilstaan juist weer een hoge frequentie nemen, zodat de loc beter blijft staan.
Rob
// PWM frequentie zetten
TCCR1B = TCCR1B & B11111000 | B00000101; // for PWM frequency of 30.64 Hz at D9/10
Net voor dit stuk // in- en output pinnen initialiseren
pinMode (richtingPin[0], OUTPUT);
pinMode (richtingPin[1], OUTPUT);
/* PULSBREEDTEBESTURING VOOR MODELTREIN
* versie 2.6 - maart 2019
* Rob van Deursen
* wijzigingen: speciale functies wat langer en 5 pulsbreedtes (i.p.v. 4)
*
* 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 40 // bereik van de potmeter buiten het midden waarop de rijstroom 0 blijft
#define geluidbereik2 80 // bereik van af de nul-grens waarop de rijstroom op de minimale waarde blijft voor de geluidsmodule
#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 A5 // functietoetsen 1 t/m 6
#define functietoets2 A4
#define functietoets3 A3
#define functietoets4 A2
#define functietoets5 A1
#define functietoets6 A0
#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 50.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 ------
#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)
//#define geluidAan2 -1.825 // snelheid om geluidsmmodule te starten (kleiner dan 0, snelheid 0 is aanloopPWM motoren)
#define geluidAan -.125 // snelheid om geluidsmmodule te starten (kleiner dan 0, snelheid 0 is aanloopPWM motoren)
#define geluidAan2 -1.375 // 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 pulsFunctie 48 // tijdsduur van de puls in ms
#define functiepulsCorrectie 4.0 // correctie voor "handmatige" puls - Arduino tijd 1/5 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 kortsluiting 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);
}
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) = led 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 deelGolf = (200000/frequentie) - functiepulsCorrectie; // lengte kwart cyclus in micro sec, minus Arduino tijd
if (IRbesturing) {deelGolf = functiePulsIRfactor * deelGolf; }
unsigned int hc = 4* deelGolf; // lengte hoge cyclus, standaard is 4/5 hoog.
unsigned int lc = 1* deelGolf; // lengte lage cyclus
if (PWMcorrectie) { // PWM correctie gevraagd
if (waardePWM < 175) { // grove PWM correctie in 1/5, 2/5, 3/5 of 4/5 pulsbreedte (4/5 is standaard)
hc = 3 * deelGolf;
lc = 2 * deelGolf;
}
if (waardePWM < 125) {
hc = 2 * deelGolf;
lc = 3 * deelGolf;
}
if (waardePWM < 75) {
hc = 1.2 * deelGolf;
lc = 3.8 * deelGolf;
}
if (waardePWM < 35) {
hc = 1 * deelGolf;
lc = 4 * deelGolf;
}
}
//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));
delay (250);
}
// ===
// === 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 < geluidbereik2 ){
s = geluidAan2;
//Serial.println("!!!!");
}
else {
if ( s < geluidbereik ){
s = geluidAan;
//Serial.println("!!!!");
}
else {
// s = (constrain (s, geluidbereik, maximaalbereik) ) - geluidbereik;
// s = 10 * s / maximaalbereik;
constrain (s, geluidbereik, maximaalbereik);
s = 8.25 * (s-geluidbereik) / (maximaalbereik-geluidbereik);
}
}
}
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 (150);}
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 0x66DC0563: b="-1G<<" ; break; //hold
case 0x496C0BC9: b="-1G>>" ; break; //reveal
// 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;
}
if (snelheid == 0 && gewensteSnelheid == geluidAan && richting == gewensteRichting ) {
snelheid == geluidAan;
}
}
// ===
// 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 && snelheid != geluidAan) { // 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 && snelheid != geluidAan) { // 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 (laatsteKnop == "-1G<" ) { // minimale stroom geluidsmodule aanzetten
if (snelheid == 0){
snelheid = geluidAan;
gewensteSnelheid = geluidAan;
acceleratie = 0;
richting = 1;
gewensteRichting = 1;
}
else {
if (richting == 1 && snelheid > 0) {
acceleratie = - acceleratieStap;
gewensteSnelheid = geluidAan;
}
}
delay(50);
}
if (laatsteKnop == "-1G>" ) { // minimale stroom geluidsmodule aanzetten
if (snelheid == 0){
snelheid = geluidAan;
gewensteSnelheid = geluidAan;
acceleratie = 0;
richting = 0;
gewensteRichting = 0;
}
else {
if (richting == 0 && snelheid > 0) {
acceleratie = - acceleratieStap;
gewensteSnelheid = geluidAan;
}
}
delay(50);
}
if (laatsteKnop == "-1G<<" ) { // minimale stroom geluidsmodule aanzetten
if (snelheid == 0){
snelheid = geluidAan2;
gewensteSnelheid = geluidAan2;
acceleratie = 0;
richting = 1;
gewensteRichting = 1;
}
else {
if (richting == 1) {
acceleratie = - acceleratieStap;
gewensteSnelheid = geluidAan2;
}
}
}
if (laatsteKnop == "-1G>>" ) { // minimale stroom geluidsmodule aanzetten
if (snelheid == 0){
snelheid = geluidAan2;
gewensteSnelheid = geluidAan2;
acceleratie = 0;
richting = 0;
gewensteRichting = 0;
}
else {
if (richting == 0) {
acceleratie = - acceleratieStap;
gewensteSnelheid = geluidAan2;
}
}
}
}
}
// ====
// 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 ----------------
#define FunctieRijden 2000 // tijd voor gecombineerde hoorn/fluit en rijgeluid bij F1 (=110 + snelheid)
#define Rangeerstand 4 // Loc heeft rangeerstand: motor start alleen als deze bewust is uitgezet (met deze functie)
Ik zou de code wat kunnen strippen.De code strippen is een goed idee. Deze sketch werkt zowel voor een IR afstandsbediening als potmeter. als je alleen de potmeter gebruikt en niet de fnctietoetsen is er inderdaad nogal wat ongebruikte code.
Wil het alleen gebruiken om te rijden en de verlichting te laten branden.
En die verlichting (in loc met LED's en in personenwagon met LED strip van 5v via een gelijkrichter, regulator en condensator) doet het al wanneer de regelaar net open staat.
Het is met deze regeling lastiger om trienen automatisch langzaam te laten optrekken en stoppen.Lastiger, maar niet heel erg lastig. Voor de IR besturing zet er al een optrek- en afrem functie in deze sketch. Het idee is dat je dan bijvoorbeeld op de "5" druk voor snelheid 5 en de loc dan langzaam versnelt of vertraagt naar deze snelheid. Misschien kun je ook iets dergelijks gebruiken.
De geluidsmodule met de testsketch herkent nu inderdaad beter de functietoetsen. Het is nog niet perfect: af en toe wordt een andere toets herkend, maar de dubbele komen nu niet meer voor.Ik heb de test sketch niet meer bijgewerkt, dus die is misschien wat minder nauwkeurig in het herkennen van de functies dan de nieuwste versie van de geluidsmodule. Belangrijk is dát een en ander herkend wordt: dan is de hardware in ieder geval goed.
Vanavond (of morgen) maar verder kijken. Uiteindelijk komt het goed.
#define MP3RX 9 // serieel receive (van MP3 speler)
#define MP3TX 8 // serieel transmit (naar MP3 speler)
Bij twijfel kun je de definities eventueel omdraaien en kijken of dat werkt. Ik heb bij mijn locs verschillende pinnen gebruikt, afhankelijk van hoe dat het beste uit kwam om in de loc in te bouwen. #define volume 24 // geluidsvolume (0-47)
#define geluid 1 // geluid altijd aan in map "01" van MP3 speler.
#define MP3inittijd 1500 // initialisatietijd MP3 speler (ms)
Ondertussen heb je veel meer locs dan je kan laten rijden lijkt me...Dan ik tegelijk kan laten rijden inderdaad... :D Maar meestal rij ik met een kleine selectie, vaak een beetje op thema, zoals 'Kleinbahn', 'De magistralen' , eenheidslocomotieven of iets dergelijks. Of ik stel gewoon een setje samen waar ik zin in heb op dat moment...
Als ik het goed begrijp gebruik je het lage deel van de PWM duty cycle (het lage % deel waarop de locmotor nog niet draait) om functies in/uit te schakelen en het hoge % deel om de snelheid te regelen.De functietoetsen werken bij stilstand én op snelheid. De snelheid wordt geregeld met de pulsbreedte, de functietoetsen veranderen voor een korte tijd de frequentie (bij dezelfde pulsbreedte). Normaliter is de frequentie 490Hz, bij de functietoetsen is deze voor elke toets hoger
Bij een loc op snelheid werken de functietoetsen dus net?
ik zal je programma nog eens goed bekijken, de laatste versie is 2.0 van mei 2018?We hebben het hier over de rijstroomregeling software. Ik heb een nieuwere versie 2.7. De belangrijkste wijziging is dat stroom niet helemaal wordt uitgezet bij de wisseling van de rijrichting. Geluid blijft dan ook aan bij rangeren, bijvoorbeeld. Maar deze versie is nog niet gepubliceerd.
(als ik alle code hier plak, krijg ik een 403 foutmelding)
Ik denk dat onze nieuwe hosting partij wat strenger is. Eventueel kun je de sketch hier als .ino file aan het bericht plakken als alternatief.Code: [Selecteer](als ik alle code hier plak, krijg ik een 403 foutmelding)
Bij testen blijkt dat de nulwaarde van de potmeters boven de stopwaarde ligt... :( Misschien andere potmeters gebruiken?Ik zie dat je 1k potmeters gebruikt. Ik gebruik 10k versies. Dat is ook wat ze in de Arduino wereld aangeven. Het zou niet zoveel uit moeten maken, want ze staan als spanningsdelers geschakeld, maar toch.
Ik denk dat onze nieuwe hosting partij wat strenger is.
/* Arduino Nano/ATmega328P (old)
* Arduino Nano/ATmega168
* Arduino Nano/Atnmega328p
*
* PULSBREEDTEBESTURING MET GELUID VOOR MODELTREIN
* versie 1.0 - januari 2023 - MH
*
* Motor snelheidsregeling met 3 snelheden en 6 functietoetsen
* Geschikt voor analoge geluidsmodules.
*
* De motorbesturing gaat met 3 open collector schakeltransistors, hier wordt
* met PWM de (effectieve) uitgangsspanning ingesteld waarmee de pulsbreedte
* tussen 0 (uit) en 255 (maximaal) wordt geregeld.
* Vaste pulsbreedte voor stop, langzaam en snel.
*
* Functietoetsen:
* Er zijn tot 6 functietoetsen aan te sluiten. Elke toets verandert kort de frequentie van de PWM rijspanning op 'stop' uitgang.
* Deze frequentieveranderingen worden door een geluidsmodule herkend en die start daarmee speciale functies.
*
*/
// ------------ Instellingen per invoerapparaat ----------
const byte aantalfunctietoetsen = 6; // 0..5
byte functietoetspin[] {2,3,4,5,6,7};
// ------------ Instellingen motorregelaar ----------
// uitvoerpinnen schakeltransistor, dit moeten PWM pinnen zijn; 3, 5, 6, 9, 10 of 11,
// analogWrite = 490 Hz op pin 3, 9, 10, 11. 980 Hz op pin 5, 6
//
// motorpinnen 0, 1, 2
byte motorpin[] {9,10,11};
//
const byte dutygeluid = 10; // ondergrens dutycycle, start geluid, maar niet voldoende om te rijden
const byte dutylangzaam = 100; // dutycycle voor langzame snelheid
const byte dutysnel = 200; // dutycycle voor hogere snelheid
//
// 0 1 2
byte dutycycle[]{dutygeluid,dutylangzaam,dutysnel}; // 0..255
//
// ------------- Definities en variabelen voor geluidsmodule pulsen -----
// rijspanning ~ 490.0 Hz; // gemeten periode bij 490 Hz = 1/490 = 2040 us voor standaard PWM rijspanning
// analogWrite 490 Hz op 3, 9, 10, 11
// analogwrite 980 Hz op 5, 6
const byte aantalfunctiefreqs = 6;
float functiefreq[] {667.0, 800.0, 1000.0, 1250.0, 1667.0, 2000.0};
const byte pulsduurfunctie = 50; // tijdsduur van de hogere frequentie functiepuls in ms
int long stopmillis; // teller duur functiepuls
//
// -------------- Overige variabelen ------------------
int t; // algemene teller
//
// ============================== subroutines =======================
void Leesfunctietoets (byte toetsnr) {
float periode, hoogpuls, laagpuls;
//
if ( digitalRead(functietoetspin[toetsnr]) == LOW ) { // toets ingedrukt
while (digitalRead(functietoetspin[toetsnr] == LOW)) { } // niets doen, wacht tot toets is losgelaten
// toets losgelaten (analogWrite gaat door op 490 Hz)
//
periode = 1000000/functiefreq[toetsnr]; // periode (hoog + laag) in usec
hoogpuls = dutycycle[0]/255 * periode; // usec, dutycycle alleen voor toetsen bij snelheid 0
laagpuls = periode - hoogpuls; // usec
//
stopmillis = millis() + pulsduurfunctie; // gedurende pulsduurfunctie in msec
while (millis() <= stopmillis) { // | pulsduur .... | alleen op 'stop' uitgang
digitalWrite(motorpin[0],HIGH); // |____ periode |____
delayMicroseconds(hoogpuls); // | | | |
digitalWrite(motorpin[0],LOW); // | | | |
delayMicroseconds(laagpuls); } //____|hoog|__laag____| |__
//
analogWrite(motorpin[0],dutycycle[0]); // terug naar standaard PWM met freq = 490 Hz
}
else { }; // niets, toets niet ingedrukt
}
// ================================== Setup na starten Arduino ========================
void setup() {
//Serial.begin(9600);
//Serial.println("Setup");
pinMode (functietoetspin[0],INPUT_PULLUP); // functietoetsen 1..6
pinMode (functietoetspin[1],INPUT_PULLUP); // toets ingedrukt = 0 (LOW)
pinMode (functietoetspin[2],INPUT_PULLUP);
pinMode (functietoetspin[3],INPUT_PULLUP);
pinMode (functietoetspin[4],INPUT_PULLUP);
pinMode (functietoetspin[5],INPUT_PULLUP);
// in- en output pinnen initialiseren
pinMode (motorpin[0], OUTPUT); // schakeluitgangen 1..3 met NPN transistor
pinMode (motorpin[1], OUTPUT);
pinMode (motorpin[2], OUTPUT);
// standaard PWM met freq = 490 Hz op motoruitgangen
analogWrite(motorpin[0],dutycycle[0]); // 'stop' uitgang
analogWrite(motorpin[1],dutycycle[1]); // 'langzaam' uitgang
analogWrite(motorpin[2],dutycycle[2]); // 'snel' uitgang
} // einde setup
// ================== Hoofdlus Arduino =================================
void loop() {
//
//Serial.println ("loop");
//
// lees functietoetsen 0..5 (1..6)
for (int t=0; t<aantalfunctietoetsen; t++ ) {
Leesfunctietoets(t); }
}
//
// ===================================================================
// --------------- einde schets -----------------------------------------------------------
(Ik denk dat het aan de max berichtlengte ligt. De code past nu blijkbaar wel.)Ik zie dat je 1k potmeters gebruikt. Ik gebruik 10k versies.Ik heb gebruikt wat ik had liggen. Met potmeters kan de snelheid in real time aangepast worden zonder het programma steeds opnieuw te hoeven compileren en uploaden.
...
En waarom gebruik je eigenlijk potmeters? Je weet toch al dat je 3 snelheden nodig hebt? Dan kun je ook drie vooraf ingestelde pulsbreedtes daarvoor gebruiken.
oscilloscoop?Een DSO201 om precies te zijn. Erg handig om snel even dingen zichtbaar te maken.
... al gevonden, DS211