Arduino som övervakar båtmotorn

Planering och tankar kring eventuella framtida projekt.
BjörnO
Inlägg: 242
Blev medlem: 3 juni 2013, 19:52:42

Re: Arduino som övervakar båtmotorn

Inlägg av BjörnO »

Tack för svaret. När det regnar nästa gång ska jag göra en testuppkoppling hemma i köket. Sedan gäller det att göra samma sak i båten, måste ha någon bra plats för dispalyen t.ex. Just nu när det är sommarväder är det båt-åka som gäller (utan motorövervakning).
BjörnO
Inlägg: 242
Blev medlem: 3 juni 2013, 19:52:42

Re: Arduino som övervakar båtmotorn

Inlägg av BjörnO »

Nu har jag gjort en första testinkoppling. Allt fungerar som det ska, även om displayen har en lite snäv betraktningsvinkel. Lite finjustering av koden och några apparatlådor och kopplingsplintar så är det dags att montera den i båten.
ImageUploadedByTapatalk1436811496.641037.jpg
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
PaNiC
Inlägg: 2565
Blev medlem: 15 augusti 2003, 22:16:15
Ort: Skånelandet

Re: Arduino som övervakar båtmotorn

Inlägg av PaNiC »

Gott :tumupp:
Funkar det fint med uppdateringsfrekvens osv?
BjörnO
Inlägg: 242
Blev medlem: 3 juni 2013, 19:52:42

Re: Arduino som övervakar båtmotorn

Inlägg av BjörnO »

Det funkar fint. Men, när jag kopplade ihop allt med lödningar och skruvplintar i stället för experimentkort fick jag bara konstiga mätvärden (+20 grader blev -125 grader). Dags att labba igen.
BjörnO
Inlägg: 242
Blev medlem: 3 juni 2013, 19:52:42

Re: Arduino som övervakar båtmotorn

Inlägg av BjörnO »

Färdiglabbat och fungerar som det ska.
ImageUploadedByTapatalk1437247857.632497.jpg
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
BjörnO
Inlägg: 242
Blev medlem: 3 juni 2013, 19:52:42

Re: Arduino som övervakar båtmotorn

Inlägg av BjörnO »

trim.16B556CB-CB9F-4FF4-9317-D82DDEA6F97E.MOV
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
DeaZ
Inlägg: 1
Blev medlem: 18 juli 2015, 14:24:05

Re: Arduino som övervakar båtmotorn

Inlägg av DeaZ »

Mycket intressant!!
Då skulle man kunna lägga till en givare för hur mycket motorn är trim/tilt i %
Få nog börja testa lite också :)
BjörnO
Inlägg: 242
Blev medlem: 3 juni 2013, 19:52:42

Re: Arduino som övervakar båtmotorn

Inlägg av BjörnO »

Nu är den på plats. Tre temperatursensorer och en hallelementsensor på motorn.
Sensorn för kylvattnet placerades på röret ut från motorn till värmeväxlaren. Sensorn för avgaserna placerades på utsidan av utloppet från limpan. Jag hittade inte någon bra plats att mäta oljetemperaturenmpå så jag fäste den tredje sensorn invid insprutarna på toppen.
Efter en misslyckad montering av magneten på svänghjulet (magneten lossnade av centrifugalkraften och bara försvann), monterade jag en annan magnet tätt intill mittmuttern på svänghjulet där den inte påverkas av så stora krafter.
Sensorkablarna samlas ihop i en låda i motorrummet och en 4-ledare leder signalerna till Arduinon som sitter i en större låda vid styrplatsen. En tredje låda på instrumentpanelen innehåller displayen.
Allt fungerar som det ska förutom att varvtalsvisningen någon gång då och då visar 6000 rpm eller ett stort värde (10 siffror). Jag tror inte det beror på störningar utan något jag missat i koden.
Kan någon av er se varför?

Kod: Markera allt

#include <DallasTemperature.h>
#include <OneWire.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>

OneWire sensorBus(4); //sensors connected to digital pin 4
DallasTemperature sensors(&sensorBus);

// Connect the LCD with SDA to analog pin 4 and SCL to analog pin 5
// set the LCD address to 0x27 (check the address)
// Set the pins on the I2C chip used for LCD connections:
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
unsigned long result = 0;

DeviceAddress Oiltemp =
{
  0x28, 0xFF, 0x18, 0x53, 0x02, 0x15, 0x04, 0x67
};
DeviceAddress Watertemp =
{
  0x28, 0xFF, 0x58, 0x54, 0x02, 0x15, 0x04, 0x08
};
DeviceAddress Exhausttemp =
{
  0x28, 0xFF, 0x07, 0x9F, 0x02, 0x15, 0x03, 0xDC
};

int alarm = 7; //the pin number of the alarm 7 

void setup()
{
  // Read and display sensor addresses
  delay(1000);
  Serial.begin(9600);
  sensors.begin();

  lcd.begin(16, 2);  // initialize the lcd for 16 chars 2 lines, turn on backlight
  // ------- Quick 3 blinks of backlight  -------------
  for(int i = 0; i < 3; i++)
  {
    lcd.backlight();
    delay(250);
    lcd.noBacklight();
    delay(250);
  }
  lcd.backlight(); // finish with backlight on

  // 3 beeps with alarm
  pinMode(alarm, OUTPUT); 
  for(int i = 0; i < 3; i++)
  {
    digitalWrite(alarm, HIGH);
    delay(250);
    digitalWrite(alarm, LOW);
    delay(250);
  }

  // NOTE: Cursor Position: (CHAR, LINE) start at 0
  lcd.setCursor(0, 0); //Start at character 0 on line 0
  lcd.print("Varvtal");  //rad 1
  lcd.setCursor(0, 1);
  lcd.print("Temperatur");  //rad 2
  delay(5000);

  attachInterrupt (0, inputPulse, RISING);  //pulse imput from rev sensor (digital pin 2)

  sensors.setResolution(Oiltemp, 10);
  sensors.setResolution(Watertemp, 10);
  sensors.setResolution(Exhausttemp, 10);

}

void loop()
{
  sensors.requestTemperatures(); // Send the command to get temperatures
  
  Serial.print(sensors.getTempCByIndex(0)); //print temp on screen
  Serial.println(" Degrees C");
  Serial.print(60000 / result); //print rpm on Screen
  Serial.println(" rpm");

  lcd.clear();
  lcd.setCursor(4, 0);
  lcd.print(60000 / result); //print rpm on display
  lcd.print(" rpm  ");

  if (6000 / result > 2500) //alarm on high rpm
  {
    digitalWrite(alarm, HIGH); //alarm signal output
    lcd.setCursor(0, 1);
    lcd.print("WARNING HIGH rpm");
    delay(2000);
  }
  else
    digitalWrite(alarm, LOW);

  sensors.requestTemperatures();
  lcd.setCursor(0, 1); //print temp on display
  lcd.print("Water:   ");
  printTemperature(Watertemp);
  delay (2000);

  lcd.clear();
  lcd.setCursor(4, 0);
  lcd.print(60000 / result); //print rpm on display
  lcd.print(" rpm  ");

  lcd.setCursor(0, 1);
  lcd.print("Oil:     ");
  printTemperature(Oiltemp);
  delay (2000);

  lcd.clear();
  lcd.setCursor(4, 0);
  lcd.print(60000 / result); //print rpm on display
  lcd.print(" rpm  ");

  lcd.setCursor(0, 1);
  lcd.print("Exhaust: ");
  printTemperature(Exhausttemp);
  delay (2000);
}


void printTemperature(DeviceAddress deviceAddress) //read sensors
{

  float tempC = sensors.getTempC(deviceAddress);

  lcd.print(tempC);
  lcd.print(" C ");

  if (tempC > 90.0) //alarm on high temp.
  {
    digitalWrite(alarm, HIGH); //alarm signal output
    lcd.setCursor(0, 0);
    lcd.print(" WARNING TEMP.  ");
    delay(2000);
  }
  else
    digitalWrite(alarm, LOW);

}// End printTemperature


void inputPulse() //interrupt - pulse input digital pin 2
{
  currentMillis = millis();                        //read millis
  result = currentMillis - previousMillis;  //rpm
  previousMillis = currentMillis;                  //prepare for next pulse

}
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
BjörnO
Inlägg: 242
Blev medlem: 3 juni 2013, 19:52:42

Re: Arduino som övervakar båtmotorn

Inlägg av BjörnO »

Lite ändringar i koden:

Kod: Markera allt

#include <DallasTemperature.h>
#include <OneWire.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>

OneWire sensorBus(4); //sensors connected to digital pin 4
DallasTemperature sensors(&sensorBus);

// Connect the LCD with SDA to analog pin 4 and SCL to analog pin 5
// set the LCD address to 0x27 (check the address)
// Set the pins on the I2C chip used for LCD connections:
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
unsigned long result = 0;
unsigned long rpm = 0;

DeviceAddress Oiltemp =
{
	0x28, 0xFF, 0x18, 0x53, 0x02, 0x15, 0x04, 0x67
};
DeviceAddress Watertemp =
{
	0x28, 0xFF, 0x58, 0x54, 0x02, 0x15, 0x04, 0x08
};
DeviceAddress Exhausttemp =
{
	0x28, 0xFF, 0x07, 0x9F, 0x02, 0x15, 0x03, 0xDC
};

int alarm = 7; //the pin number of the alarm

float tempC;

void setup()
{
	// Read and display sensor addresses
	delay(1000);
	Serial.begin(9600);
	sensors.begin();

	lcd.begin(16, 2);  // initialize the lcd for 16 chars 2 lines, turn on backlight
	// ------- Quick 3 blinks of backlight  -------------
	for(int i = 0; i < 3; i++)
	{
		lcd.backlight();
		delay(250);
		lcd.noBacklight();
		delay(250);
	}
	lcd.backlight(); // finish with backlight on

	// 3 beeps with alarm
	pinMode(alarm, OUTPUT);
	for(int i = 0; i < 3; i++)
	{
		digitalWrite(alarm, HIGH);
		delay(250);
		digitalWrite(alarm, LOW);
		delay(250);
	}

	// NOTE: Cursor Position: (CHAR, LINE) start at 0
	lcd.setCursor(0, 0); //Start at character 0 on line 0
	lcd.print("Varvtal");  //rad 1
	lcd.setCursor(0, 1);
	lcd.print("Temperatur");  //rad 2
	delay(5000);

	attachInterrupt (0, inputPulse, RISING);  //pulse imput from rev sensor (digital pin 2)

	sensors.setResolution(Oiltemp, 10);
	sensors.setResolution(Watertemp, 10);
	sensors.setResolution(Exhausttemp, 10);

	lcd.clear();
}

void loop()
{

	sensors.requestTemperatures();
	lcd.setCursor(0, 1); //print temp on display
	lcd.print("Water:   ");
	printTemperature(Watertemp);

	if (tempC > 70) //alarm on high temp.
	{
		digitalWrite(alarm, HIGH); //alarm signal output
		lcd.setCursor(0, 0);
		lcd.print(" WARNING TEMP.  ");
		delay(1000);
	}
	else
		digitalWrite(alarm, LOW);
	

	lcd.setCursor(0, 1);
	lcd.print("Oil:     ");
	printTemperature(Oiltemp);

	if (tempC > 100) //alarm on high temp.
	{
		digitalWrite(alarm, HIGH); //alarm signal output
		lcd.setCursor(0, 0);
		lcd.print(" WARNING TEMP.  ");
		delay(1000);
	}
	else
		digitalWrite(alarm, LOW);

	lcd.setCursor(0, 1);
	lcd.print("Exhaust: ");
	printTemperature(Exhausttemp);

	if (tempC > 70) //alarm on high temp.
	{
		digitalWrite(alarm, HIGH); //alarm signal output
		lcd.setCursor(0, 0);
		lcd.print(" WARNING TEMP.  ");
		delay(1000);
	}
	else
		digitalWrite(alarm, LOW);
}

void printTemperature(DeviceAddress deviceAddress) //read sensors and print result
{
// Read temp
	float tempC = sensors.getTempC(deviceAddress);
// Print temp
	lcd.print(tempC);
	lcd.print(" C ");

// Print RPM
	rpm = 60000 / result;

	if (rpm < 4000) //filter out invalid readings
	{

		lcd.setCursor(4, 0);
		lcd.print(rpm); //print rpm on display
		lcd.print(" rpm  ");

		if (rpm > 2500) //alarm on high rpm
		{
			digitalWrite(alarm, HIGH); //alarm signal output
			lcd.setCursor(0, 1);
			lcd.print("WARNING HIGH rpm");
			delay(1000);
		}
		else
			digitalWrite(alarm, LOW);
		delay(1000);
	}

}// End printTemperature


void inputPulse() //interrupt - pulse input digital pin 2
{
	currentMillis = millis();                        //read millis
	result = currentMillis - previousMillis;  //rpm
	previousMillis = currentMillis;                  //prepare for next pulse
}
BjörnO
Inlägg: 242
Blev medlem: 3 juni 2013, 19:52:42

Re: Arduino som övervakar båtmotorn

Inlägg av BjörnO »

Det gick inte alls. Den visar ibland brara två temperaturer och ibland bara en. Dessutom blir det felaktigt övervarvslarm oftare än tidigare. Jag skulle uppskatta ett tips.
Jag får justera koden och försöka igen. Tyvärr kan jag inte ta med datorn till båten, är tvungen att ta hem Arduinon och justera koden och någon dag senare testa.
Användarvisningsbild
Jan Almqvist
Inlägg: 1580
Blev medlem: 1 oktober 2013, 20:48:26
Ort: Orust

Re: Arduino som övervakar båtmotorn

Inlägg av Jan Almqvist »

Är det OK att anropa funktionen millis() från interruptet som du gör?

Edit: Om interruptet inkl. anrop till millis() tar lång kan du få ett nytt interrupt innan du är klar med det första dvs du kanske har ett reentrancy-problem?

Ett alternativ vore annars att bara räkna upp en räknare för antal pulser där. Anrop av millis(), nollställning av räknare och uträkning skulle isf. kunna göras i funktionen loop() med ett visst tidsintervall t.ex var 100:e eller 1000:e ms.

(Anar att denna metod skulle nog behöva någon slags glidande medelvärdesberäkning för att bli stabil, ffa på låga varv.)
BjörnO
Inlägg: 242
Blev medlem: 3 juni 2013, 19:52:42

Re: Arduino som övervakar båtmotorn

Inlägg av BjörnO »

Tidsintervallet mellan interrupt är alltid mer än 20 ms. Jag trodde att dessa kommandon skulle hinnas med. Egentligen sparar jag ju bara millis-värdet:

Kod: Markera allt

void inputPulse() 
{
   currentMillis = millis();                        
   result = currentMillis - previousMillis;  
   previousMillis = currentMillis;    
}
Jag förstår inte riktigt hur jag ska göra för att få till det du föreslår.
Användarvisningsbild
Jan Almqvist
Inlägg: 1580
Blev medlem: 1 oktober 2013, 20:48:26
Ort: Orust

Re: Arduino som övervakar båtmotorn

Inlägg av Jan Almqvist »

Jag var förmodligen på fel spår men såg kanske en annan sak när jag googlade. Kan det behövas ett 'volatile' i din kod?

Kod: Markera allt


volatile unsigned long result = 0;

https://www.arduino.cc/en/Reference/Volatile
BjörnO
Inlägg: 242
Blev medlem: 3 juni 2013, 19:52:42

Arduino som övervakar båtmotorn

Inlägg av BjörnO »

Jag ska ta bort övervarvslarmet och lägga in "volatile". Testar i helgen.
Kanske Metro library eller Timer library skulle vara en annan lösning. Då kan interrupten bara räkna pulser.
MiaM
Inlägg: 9903
Blev medlem: 6 maj 2009, 22:19:19

Re: Arduino som övervakar båtmotorn

Inlägg av MiaM »

Jag skulle nog deklarerat variablerna globalt (dvs utanför funktionen), då överlever de ju garanterat, fast risken är ju att man råkar använda dem på fel ställe.

Jag har inte orkat kolla på din kod, men jag har som nån labb tidigare skrivit en 'frekvensmätar'-kod som mäter tiden på övre och undre flanken på inkommande signal på en digitalingång, interruptstyrt, och det verkade funka riktigt bra utan "fladder". Jag är rätt säker på att jag använde micros och inte millis. Micros verkar wrappa efter 70 minuter, se till att det blir rätt med aritmetiken både kring detta och signed/unsigned.

P.S. en vanlig funktionsgenerator, gärna med TTL-utgång, är rätt bra att ha för att testa den här typen av grejer. När jag labbade använde jag en funktionsgenerator som dessutom har ställbar asymetri på fyrkantvåg. Jag körde dessutom med en extern frekvensmätare parallellt (fast på "vanliga" utgången) och enligt den så mätte min kod förhållandevis rätt.

För en varvräknare så kan det kanske vara en bra idé att lagra ett antal mätningar i en ringbuffert och visa medelvärde på de senaste mätningarna om de senaste är tillräckligt nära varandra, för att slippa fladder i visningen. När varvtalet ändras snabbare så är det däremot vettigt att visa senaste utan medelvärdesbildning för att få så snabb visning som möjligt, antar jag.
Skriv svar