Sketch problem



  • I have a sketch with some sensors. But the two that plays a part in this drama is the Temperature sensor and a Relay.
    Every time when the sketch report a new temperature value I also get a SET message for the relay.

    If you need to see the whole sketch let me know.

    This is how I report the new temperature.

    MyMessage tempMsg(TEMP_ID, V_TEMP);
    send(tempMsg.set(tempC, 1));
    

    And this is the output from MYSController:

    688	2016-10-16 11:40:33	RX	1 - FishTank	1 - Water temperature	C_SET	NO	V_TEMP	25.7
    690	2016-10-16 11:40:35	RX	1 - FishTank	2 - Water valve	C_SET	YES	V_LIGHT	0
    691	2016-10-16 11:40:39	RX	1 - FishTank	1 - Water temperature	C_SET	NO	V_TEMP	26.2
    692	2016-10-16 11:40:39	RX	1 - FishTank	2 - Water valve	C_SET	YES	V_LIGHT	0
    694	2016-10-16 11:40:45	RX	1 - FishTank	1 - Water temperature	C_SET	NO	V_TEMP	26.1
    695	2016-10-16 11:40:45	RX	1 - FishTank	2 - Water valve	C_SET	YES	V_LIGHT	0
    697	2016-10-16 11:41:03	RX	1 - FishTank	1 - Water temperature	C_SET	NO	V_TEMP	26.0
    698	2016-10-16 11:41:03	RX	1 - FishTank	2 - Water valve	C_SET	YES	V_LIGHT	0
    700	2016-10-16 11:41:09	RX	1 - FishTank	1 - Water temperature	C_SET	NO	V_TEMP	25.9
    701	2016-10-16 11:41:09	RX	1 - FishTank	2 - Water valve	C_SET	YES	V_LIGHT	0
    

  • Hero Member

    @raptorjr Can you post the complete sketch in order to find the cause?



  • @AWI

    Sure.

    // Enable serial gateway
    //#define MY_GATEWAY_SERIAL 
    
    // Enable debug prints to serial monitor
    //#define MY_DEBUG 
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    
    #include <SPI.h>
    #include <MySensors.h>  
    #include <OneWire.h>
    #include <DallasTemperature.h>
    
    #define TEMP_ID 1
    #define RELAY_ID 2
    #define WATERFLOW_ID 3
    
    //Temperatur sensor
    #define ONE_WIRE_BUS 4
    #define COMPARE_TEMP 1 // Send temperature only if changed? 1 = Yes 0 = No
    float lastTemperature = 0;
    MyMessage tempMsg(TEMP_ID, V_TEMP); // Initialize temperature message
    OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature. 
    unsigned long SLEEP_TIME = 5000; // Sleep time between reads (in milliseconds)
    
    //Relay to water valve
    #define RELAY_PIN 5  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define RELAY_ON 1   // GPIO value to write to turn on attached relay
    #define RELAY_OFF 0  // GPIO value to write to turn off attached relay
    
    //Waterflow meter
    #define WATERFLOW_PIN 3
    #define WATERFLOW_INTERRUPT WATERFLOW_PIN - 2
    // The hall-effect flow sensor outputs approximately 4.5 pulses per second per
    // litre/minute of flow.
    float calibrationFactor = 4.5;
    volatile unsigned long pulseCounter = 0;
    float flowRate = 0;
    float flowLitres = 0;
    float totalLitres = 0;
    unsigned long oldTime = 0;
    MyMessage flowMsg(WATERFLOW_ID, V_FLOW);
    MyMessage volumeMsg(WATERFLOW_ID, V_VOLUME);
    
    void setup(void)
    {
    	// start serial port
    	Serial.begin(115200);
    
    	pinMode(RELAY_PIN, OUTPUT);
    	digitalWrite(RELAY_PIN, RELAY_OFF);
    
    	pinMode(WATERFLOW_PIN, INPUT);
    	digitalWrite(WATERFLOW_PIN, HIGH);
    
    	// The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
    	// Configured to trigger on a FALLING state change (transition from HIGH
    	// state to LOW state)
    	attachInterrupt(WATERFLOW_INTERRUPT, onPulse, FALLING);
    
    }
    
    void presentation() 
    {
    	// Send the sketch version information to the gateway and Controller
    	sendSketchInfo("FishTank", "1.0");
    
    	present(TEMP_ID, S_TEMP, "Water temperature");
    
    	present(RELAY_ID, S_BINARY, "Water valve");
    
    	present(WATERFLOW_ID, S_WATER, "Water flow");
    
    	send(volumeMsg.set(totalLitres, 2));
    
    }
    
    void loop(void)
    {
    	DeviceAddress tempDeviceAddress; // We'll use this variable to store a found device address    
    	// For testing purposes, reset the bus every loop so we can see if any devices appear or fall off
    	sensors.begin();
    	sensors.requestTemperatures(); // Send the command to get temperatures
    	
    	// Search the wire for address
       if(sensors.getAddress(tempDeviceAddress, 0))
       {
    		float tempC = round(sensors.getTempC(tempDeviceAddress) * 10) / 10.0;
    		Serial.print("Temperature=");
    		Serial.print(tempC);
    		Serial.print(", LastTemp=");
    		Serial.println(lastTemperature);
    #if COMPARE_TEMP == 1
    		// Only send data if temperature has changed and no error
    		if (lastTemperature != tempC && tempC != -127.00 && tempC != 85.00)
    		{
    #else
    		if (tempC != -127.00 && tempC != 85.00)
    		{
    #endif
    			// Send in the new temperature
    			send(tempMsg.set(tempC, 1));
    			// Save new temperatures for next compare
    			lastTemperature = tempC;
    		}
       } 
    
    	if ((millis() - oldTime) > 1000)    // Only process counters once per second
    	{
    		// Disable the interrupt while calculating flow rate and sending the value to
    		// the host
    		detachInterrupt(WATERFLOW_INTERRUPT);
    
    		// Because this loop may not complete in exactly 1 second intervals we calculate
    		// the number of milliseconds that have passed since the last execution and use
    		// that to scale the output. We also apply the calibrationFactor to scale the output
    		// based on the number of pulses per second per units of measure (litres/minute in
    		// this case) coming from the sensor.
    		flowRate = ((1000.0 / (millis() - oldTime)) * pulseCounter) / calibrationFactor;
    		
    		if(flowRate > 0)
    			send(flowMsg.set(flowRate, 2));
    
    		// Note the time this processing pass was executed. Note that because we've
    		// disabled interrupts the millis() function won't actually be incrementing right
    		// at this point, but it will still return the value it was set to just before
    		// interrupts went away.
    		oldTime = millis();
    
    		// Divide the flow rate in litres/minute by 60 to determine how many litres have
    		// passed through the sensor in this 1 second interval, then multiply by 1000 to
    		// convert to millilitres.
    		flowLitres = (flowRate / 60);
    
    		// Add the millilitres passed in this second to the cumulative total
    		totalLitres += flowLitres;
    
    		if(totalLitres > 0)
    			send(volumeMsg.set(totalLitres, 2));
    
    		unsigned int frac;
    
    		// Print the flow rate for this second in litres / minute
    		Serial.print("Flow rate: ");
    		Serial.print(int(flowRate));  // Print the integer part of the variable
    		Serial.print(".");             // Print the decimal point
    												 // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
    		frac = (flowRate - int(flowRate)) * 10;
    		Serial.print(frac, DEC);      // Print the fractional part of the variable
    		Serial.print("L/min");
    		// Print the number of litres flowed in this second
    		//Serial.print("  Current Liquid Flowing: ");             // Output separator
    		//Serial.print(flowLitres);
    		//Serial.print("L/Sec");
    
    		// Print the cumulative total of litres flowed since starting
    		Serial.print("  Output Liquid Quantity: ");             // Output separator
    		Serial.print(totalLitres);
    		Serial.println("L");
    
    		// Reset the pulse counter so we can start incrementing again
    		pulseCounter = 0;
    
    		// Enable the interrupt again now that we've finished sending output
    		attachInterrupt(WATERFLOW_INTERRUPT, onPulse, FALLING);
    	}
    
    
    	wait(SLEEP_TIME);
    }
    
    void receive(const MyMessage &message) 
    {
    	// We only expect one type of message from controller. But we better check anyway.
    	if (message.type == V_STATUS && message.sensor == RELAY_ID)
    	{
    		// Change relay state
    		digitalWrite(RELAY_PIN, message.getBool() ? RELAY_ON : RELAY_OFF);
    		// Write some debug info
    		Serial.print("Incoming change for sensor:");
    		Serial.print(message.sensor);
    		Serial.print(", New status: ");
    		Serial.println(message.getBool());
    
    		if (message.getBool() == RELAY_ON) //Reset the total litres, so we can start fresh when we open the valve
    		{
    			totalLitres = 0;
    			send(volumeMsg.set(totalLitres, 2));
    		}
    	}
    }
    
    void onPulse()
    {
    	// Increment the pulse counter
    	pulseCounter++;
    }
    

  • Hero Member

    @raptorjr I cannot find the cause 😕 What does the serial output of the node tell you?



  • @AWI

    It is kind of the same thing. Every time I report a temperature, the receive function get triggered. And when temperature is not changed and reported, no message about the relay.

    Temperature=25.10, LastTemp=25.10
    Flow rate: 0.0L/min Output Liquid Quantity: 0.03L
    Temperature=25.20, LastTemp=25.10
    Flow rate: 0.0L/min Output Liquid Quantity: 0.03L
    Incoming change for sensor:2, New status: 0
    Temperature=25.10, LastTemp=25.20
    Flow rate: 0.0L/min Output Liquid Quantity: 0.03L
    Incoming change for sensor:2, New status: 0
    Incoming change for sensor:2, New status: 0
    Temperature=25.10, LastTemp=25.10
    Flow rate: 0.0L/min Output Liquid Quantity: 0.03L
    Temperature=25.10, LastTemp=25.10
    Flow rate: 0.0L/min Output Liquid Quantity: 0.03L
    Temperature=25.10, LastTemp=25.10


  • Hero Member

    @raptorjr can you switch debug on? #define MY_DEBUG . It could be possible that the controller sends an Ack..



  • @AWI

    There is something about ACK that I did see in the MYSController. Every relay message has ACK = YES. Can that be a problem, and what can I do about it?

    0_1476613867851_2016-10-16_1230.png


  • Hero Member

    @raptorjr It is good practice to use "ACK" when actuating a switch. That way you the controller can check if the message arrived (if the action took place). To debug you should look at the debug log to see what kind of message's are actually sent and received.



  • @AWI

    This is what I get with debug turned on:

    Temperature=25.10, LastTemp=25.10
    Flow rate: 0.0L/min  Output Liquid Quantity: 0.00L
    Temperature=25.00, LastTemp=25.10
    TSF:MSG:SEND,1-1-0-0,s=1,c=1,t=0,pt=7,l=5,sg=0,ft=0,st=OK:25.0
    Flow rate: 0.0L/min  Output Liquid Quantity: 0.00L
    TSF:MSG:READ,0-0-1,s=2,c=1,t=2,pt=0,l=1,sg=0:0
    TSF:MSG:ACK REQ
    TSF:MSG:SEND,1-1-0-0,s=2,c=1,t=2,pt=0,l=1,sg=0,ft=0,st=OK:0
    Incoming change for sensor:2, New status: 0
    Temperature=25.10, LastTemp=25.00
    !TSF:MSG:SEND,1-1-0-0,s=1,c=1,t=0,pt=7,l=5,sg=0,ft=0,st=NACK:25.1
    Flow rate: 0.0L/min  Output Liquid Quantity: 0.00L
    Temperature=25.10, LastTemp=25.10
    Flow rate: 0.0L/min  Output Liquid Quantity: 0.00L
    

Log in to reply
 

408
Online

6.7k
Users

7.6k
Topics

80.3k
Posts

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.