Sida 1 av 3
Arduino som övervakar båtmotorn
Postat: 26 december 2013, 14:26:22
av BjörnO
När jag förra året funderade på att förse min gamla båtmotor med en varvräknare fick jag ett förslag att lösa det med en Arduino. Då löste jag det i stället med en billig cykeldator.
Men - tanken slog rot och jag har just köpt en Arduino. Nu gäller det att plocka fram 40 år gamla programmeringskunskaper.
En enkel varvräknare får det bli till att börja med. Bara en rad lysdioder som visar några valda varvtal (marschvarv, maxvarv och några nivåer till).
Här är förslag på kod. Kommentarer mottages tacksamt:
Kod: Markera allt
/*
UNO board.
Takes rpm samples via ADC pin, and shows the value on LEDs.
*/
// revmeter, pulse input on pin 2 ----------------------------------------------
int ledR1 = 3; //the number of the pin red LED
int ledR2 = 4; //yellow
int ledR3 = 5; //green
int ledR4 = 6; //green
int ledR5 = 7; //green
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
unsigned long result = 0;
int pin13 = 13;
void setup()
{
// revmeter setup --------------------------------------------------------------------
pinMode(ledR1, OUTPUT); //LED array
pinMode(ledR2, OUTPUT);
pinMode(ledR3, OUTPUT);
pinMode(ledR4, OUTPUT);
pinMode(ledR5, OUTPUT);
attachInterrupt (0, inputPulse, RISING); //pulse imput from rev sensor
}
void loop()
{
// revmeter loop ------------------------------------------------------------
if (result > (60000 / 2500)) //2500 rpm (max rpm)
digitalWrite(ledR1, HIGH);
else
digitalWrite(ledR1, LOW);
if (result > (60000 / 2000)) //2000 rpm (cruising speed)
digitalWrite(ledR2, HIGH);
else
digitalWrite(ledR2, LOW);
if (result > (60000 / 1500)) //1500 rpm
digitalWrite(ledR3, HIGH);
else
digitalWrite(ledR3, LOW);
if (result > (60000 / 1000)) //1000 rpm
digitalWrite(ledR4, HIGH);
else
digitalWrite(ledR4, LOW);
if (result > (60000 / 700)) //700 rpm (idle)
digitalWrite(ledR5, HIGH);
else
digitalWrite(ledR5, LOW);
}
// revmeter interrupt ----------------------------------------------------------
void inputPulse()
{
currentMillis = millis(); //read millis
result = currentMillis - previousMillis; //calculate time
previousMillis = currentMillis; //save last pulse and prepare for next pulse
}
Re: Arduino som övervakar båtmotorn
Postat: 26 december 2013, 16:47:21
av JanErik
Jag skulle nog sätta ett kort flytande medelvärde, dvs en cirkulär buffer på kanske fem "result" för att få stabilare mätvärde.
Re: Arduino som övervakar båtmotorn
Postat: 26 december 2013, 16:47:50
av blueint
Fanns väl inte mycket till C programmering 1973 ?
Re: Arduino som övervakar båtmotorn
Postat: 26 december 2013, 17:08:05
av BjörnO
Nej, C fanns inte då. Jag programmerade i Fortran-4 och maskinspråk för 3-bitars datorer uppbyggda av transistorer. När de första mikrodatorkretsarna kom byggde jag mig en egen dator, långt innan någon kunde stava till PC. Förutom ett eller annat DOS-kommando och någon redigering av PostScript har jag inte programmerat sedan dess.
Det blir att bläddra bland kommandon i manualen och försöka välja något lämpligt.
Re: Arduino som övervakar båtmotorn
Postat: 27 december 2013, 23:31:57
av BjörnO
Eftersom mitt första önskemål var en analog varvräknare kopplar jag ett instrument till en pwm-utgång med följande kod:
Kod: Markera allt
int meterOut = 9; //analog out
analogWrite(meterOut, 3825 / result) //analog out to meter (0-4000 rpm = 0-5V)
Re: Arduino som övervakar båtmotorn
Postat: 28 december 2013, 18:47:21
av BjörnO
Kompletterade med medelvärde. Så här ser det ut nu:
Kod: Markera allt
/*
UNO board.
Takes rpm samples via ADC pin, and shows the value on five LEDs.
also outputs an pwm signal to analog meter
*/
// revmeter, pulse input on pin 2 ----------------------------------------------
int ledR1 = 3; //the pin number of the red LED
int ledR2 = 4; //yellow
int ledR3 = 5; //green
int ledR4 = 6; //green
int ledR5 = 7; //green
int meterOut = 9; //analog out
int a = 0;
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
unsigned long partresult[6] = {0, 0, 0, 0, 0};
unsigned long result = 0;
int pin13 = 13;
void setup()
{
// revmeter setup --------------------------------------------------------------
pinMode(ledR1, OUTPUT); //LED array
pinMode(ledR2, OUTPUT);
pinMode(ledR3, OUTPUT);
pinMode(ledR4, OUTPUT);
pinMode(ledR5, OUTPUT);
attachInterrupt (0, inputPulse, RISING); //pulse imput from rev sensor
}
void loop()
{
// revmeter loop -----------------------------------------------------------
if (result > (60000 / 2500)) //2500 rpm (max rpm)
digitalWrite(ledR1, HIGH);
else
digitalWrite(ledR1, LOW);
if (result > (60000 / 2000)) //2000 rpm (cruising speed)
digitalWrite(ledR2, HIGH);
else
digitalWrite(ledR2, LOW);
if (result > (60000 / 1500)) //1500 rpm
digitalWrite(ledR3, HIGH);
else
digitalWrite(ledR3, LOW);
if (result > (60000 / 1000)) //1000 rpm
digitalWrite(ledR4, HIGH);
else
digitalWrite(ledR4, LOW);
if (result > (60000 / 700)) //700 rpm (idle)
digitalWrite(ledR5, HIGH);
else
digitalWrite(ledR5, LOW);
analogWrite(meterOut, 3825 / result); //analog out to meter (0-4000 rpm = 0-5V)
}
// revmeter interrupt ----------------------------------------------------------
void inputPulse()
{
currentMillis = millis(); //read millis
partresult[a] = currentMillis - previousMillis; //calculate time
previousMillis = currentMillis; //save last pulse and prepare for next pulse
result = (partresult[0] + partresult[1] + partresult[2] + partresult[3] + partresult[4]) / 5; //mean value of 5 results
a += 1; //next step
if (a = 5) //reset if end
{
a = 0;
}
}
Edit: Rättade koden.
Re: Arduino som övervakar båtmotorn
Postat: 28 december 2013, 19:11:56
av PopUnoNkoK
Jag blir nyfiken på hur hårdvaran ser ut. Alltså själva varvräknar delen, input.
Blir säkert snyggt med analog visare, på rätt båt förstås. =)
mvh Peter
Re: Arduino som övervakar båtmotorn
Postat: 28 december 2013, 19:50:33
av BjörnO
Hårdvaran för varvräknaren blir i första hand den som jag redan monterat, dvs en magnet på svänghjulet och cykeldatorns sensor, se
http://elektronikforumet.com/forum/view ... 37#p962837. Jag vet att jag har en hallelementsensor liggande någonstans. Kanske jag hittar den innan det är dags.
Mitt problem är att jag inte kan testa förrän efter sjösättningen i vår, så det får bli "torrsim" i stället. Kanske jag kan göra en mockup med en boorrmaskin som svänghjul.
Re: Arduino som övervakar båtmotorn
Postat: 20 januari 2014, 20:37:26
av BjörnO
Kom på att jag kunde använda en andra Arduino som kan mata ut pulser och fungera som motor. Här är lite kod för den:
Kod: Markera allt
/*
/*
UNO board.
Emits pulses for testing of the RPM meter.
20 ms between pulses (at 3000 rpm) to 90 ms between pulses (at 666 rpm)
One 0.1 ms pulse each pulse time during 10 s.
Then next pulse time in sequence until 90 ms.
*/
unsigned long pM = 0; //pulse time
unsigned long sM = 0; //sequence time
unsigned long M = 0; //time
int pT = 10;
int count = 0;
int out = 13; //pulse output pin
void setup()
{
pinMode(out, OUTPUT);
Serial.begin(9600);
delay(10000); //delay 1 s to allow time to start serial monitor
}
void loop()
{
M = millis(); //read millis and save
if (M < pM + pT) //when time for a pulse - emit pulse
return;
digitalWrite(out, HIGH);
delayMicroseconds(100);
digitalWrite(out, LOW);
pM = M; //start over
if(M < sM + 10000) //after 10 s - next pulse time
return;
pT = pT + 10;
sM = M; //start over
Serial.println(pT); //print speed
if(pT < 90) //when all speeds are done - start from the beginning
return;
pT = 10;
}
och så här ser varvräknarkoden ut nu:
Kod: Markera allt
/*
UNO board.
Takes rpm samples via ADC pin, and shows the value on five LEDs.
also outputs a pwm signal to analog meter
*/
// revmeter setup, pulse input on pin 2 ----------------------------------------
int ledR1 = 3; //the pin number of the red LED
int ledR2 = 4; //yellow
int ledR3 = 5; //green
int ledR4 = 6; //green
int ledR5 = 7; //green
int meterOut = 9; //analog out
int a = 0;
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
unsigned long partresult[6] = {0, 0, 0, 0, 0};
unsigned long result = 0;
int pin13 = 13;
void setup()
{
pinMode(ledR1, OUTPUT); //LED array
pinMode(ledR2, OUTPUT);
pinMode(ledR3, OUTPUT);
pinMode(ledR4, OUTPUT);
pinMode(ledR5, OUTPUT);
attachInterrupt (0, inputPulse, RISING); //pulse imput from rev sensor
}
void loop()
{
// revmeter loop to display values on LEDs ---------------------------------
analogWrite(meterOut, 3825 / result); //analog out to meter (0-4000 rpm = 0-5V)
if ((result < (60000 / 700)) and (result >= (60000 / 1000))) //700-1000 rpm (idle) 85,7-60
digitalWrite(ledR5, HIGH);
else
digitalWrite(ledR5, LOW);
if ((result < (60000 / 1000)) and (result >= (60000 / 1500))) //1000-1500 rpm 60-40
digitalWrite(ledR4, HIGH);
else
digitalWrite(ledR4, LOW);
if ((result < (60000 / 1500)) and (result >= (60000 / 2000))) //1500-2000 rpm 40-30
digitalWrite(ledR3, HIGH);
else
digitalWrite(ledR3, LOW);
if ((result < (60000 / 2000)) and (result >= (60000 / 2500))) //2000-2500 rpm (cruising speed) 30-24
digitalWrite(ledR2, HIGH);
else
digitalWrite(ledR2, LOW);
if (result < (60000 / 2500)) //2500 rpm (max rpm) 24
digitalWrite(ledR1, HIGH);
else
digitalWrite(ledR1, LOW);
}
// revmeter interrupt ----------------------------------------------------------
void inputPulse()
{
currentMillis = millis(); //read millis
partresult[a] = currentMillis - previousMillis; //time between pulses
previousMillis = currentMillis; //prepare for next pulse
result = (partresult[0] + partresult[1] + partresult[2] + partresult[3] + partresult[4]) / 5; //mean value of 5 results
a = a + 1; //next step
if (a == 5)
{
a = 0; //start over if end
}
}
Nu ser det ut att fungera:
Om någon ser att jag gjort något konstigt så säg till.
/Björn
Re: Arduino som övervakar båtmotorn
Postat: 1 juli 2015, 22:03:18
av BjörnO
Nu har jag dammat av projektet igen.
Ett första steg kommer att övervaka tre temperaturer i motorrummet och motorns varvtal. Med tre i2c- temeratursensorer och en i2c- display blir ledningsdragningen minimal för temperaturövervakningen. Hallelementsensorn koplar jag som tidigare till en inerruptingång.
Läsa av temperaturerna och visa resultatet på displayen verkar ganska enkelt. Men hur går det när interrupten bryter in, upp till 3000 gånger per minut?
Re: Arduino som övervakar båtmotorn
Postat: 3 juli 2015, 16:30:19
av PaNiC
Interrupten avbryter ju allt annat du håller på med, så man gör klokt i att hålla interruptrutinerna så korta som möjligt. Nu vet jag inte hur det funkar med Arduino, men hade du använt AVRen "ren" så hade du kunnat koppla pulsgivaren direkt till timer/countern genom hårdvara, så hade du sluppit interruptrutinen där, men kanske fått ha en timer-interrupt istället för att läsa av räknaren. Men den hade du ju då kunnat hålla till displayens uppdateringsintervall istället, säg 1-2 ggr/sek.
Re: Arduino som övervakar båtmotorn
Postat: 3 juli 2015, 19:57:12
av BjörnO
Dilemmat är att om jag inte använder interrupt kanske jag missar pulser och om jag använder interrupt stör jag displayhanteringen. Kanske jag skulle dela ner pulsfrekvensen. Jag har en 4017 liggande så jag kan lätt dela med 10 och få intervallet 50-300 pulser per minut. Jag behöver inte läsa av temperaturerna oftare än med minutintervall och kanske behöver uppdatera displayen med några sekunders intervall.
Re: Arduino som övervakar båtmotorn
Postat: 3 juli 2015, 23:07:21
av PaNiC
Jo jag förstår det, men om man använder hårdvarucountern på sättet som jag beskrev så slipper man de problemen.
Re: Arduino som övervakar båtmotorn
Postat: 4 juli 2015, 16:34:19
av BjörnO
Att använda hårdvarucountern blir nog att ta sig vatten över huvudet för mig, får försöka på enklare sätt. Jag har några ideer:
1) att göra "allt" i interruptrutinen och på så sätt hindra interrupten att bryta in. Men det går nog inte utan neddelning av pulsfrekvensen eftersom jag i värsta fall bara har 20 ms på mig (med neddelning 200 ms).
2) att bara läsa av tiden i interruptrutinen och göra allt annat utanför. Hur går det då när interrupten kommer mitt i kommunikationen över i2c-bussen?
3) att stänga av interrupten när jag vill kommunicera med i2c. Då får jag ett ogiltigt värde när jag slår på interrupten igen, men det får jag i så fall filtrera bort.
Re: Arduino som övervakar båtmotorn
Postat: 4 juli 2015, 17:09:41
av PaNiC
Att göra allt i interruptrutinen är inte att rekommendera. Lustiga fenomen uppstår om interruptet triggar igen om den inte är färdig.
Det enda du bör göra i interruptrutinen är att öka en räknare, som du sedan använder för att räkna ut varvtalet.
I2C är ett synkront protokoll, så ingenting konstigt bör hända om du håller avbrottet inom rimlighetens gränser.