Jump to content

Banner.jpg.b83b14cd4142fe10848741bb2a14c66b.jpg

DIY cloud and rain sensor with ascom support?


Corpze

Recommended Posts

Hi, i am wondering if there is any diy cloud and rain sensor project with ascom support? (Safety monitor)

I built one with a ebay rain sensor and a mlx cloud sensor (ir) and used it with SGL cloud sensor evo, working nice (using only the cloud sensor)

But the lack of ascom support makes it fairly useless for me as i need the safety monitor support for my automated observatory.

Is there any ascom driver for this?

Link to comment
Share on other sites

Hi Corpze, I would also like to hear about this. Ideally I would like an ASCOM driver that interfaces an Arduino Mega to the ASCOM Safety Monitor. I am happy to connect my cloud and rain sensors to the Arduino - as well as lots of other bits and pieces - but I have no idea how to get the safety status information shared with ASCOM. 

Regards, Hugh

Link to comment
Share on other sites

I have started to write (as simple as possible) code to my Arduino Nano clone.

It is a rain sensor: http://www.dx.com/p/raindrops-sensor-module-blue-black-199859#.VAaJLmOrjfV

A DS18B20 temperature sensor: https://www.sparkfun.com/products/11050

And a MLX90614 IR sensor: http://www.ebay.com/itm/1PC-MLX90614-Contactless-Temperature-Sensor-Module-For-Arduino-Compatible-New-/400837282279?pt=LH_DefaultDomain_15&hash=item5d53c389e7

How it´s connected is shown in the code.

I got the code working well, printing out this in the serial monitor:

DS18B20  Temperature: 25.00 Celsius

MLX90614 Temperature: 26.96 Celsius
DELTA Temperature: -1.96 Celsius
Rain sensor status:     Not Raining
I will change the code to print out the best value for the Ascom safety monitor, probably just "IsSafe"
Here is the help section of the Ascom safety monitor; http://ascom-standards.org/Help/Platform/Index.html
If it is rain it will immediately send nothing (I believe Ascom safety monitor listens to "IsSafe"?)
The trick is to not trigger the safety monitor with each small cloud, but maybe after a five-minute period of clouds?
If the Delta temperature is below -21C it is clouds present, if the Delta temperature is higher than -25C it is most certain no clouds (between -21C and -25C there is probably small cirrus or similar)
The Arduino code Should not be that hard to code, but the ascot safety monitor driver must be written on a windows pc... and i am a Mac user... maybe there is someone who wan´t to give this a go? ;)
Best Regards, Daniel
Link to comment
Share on other sites

I started Making a cloud sensor/Rain sensor some time ago with the Arduino but struggling with the codes I have just switched over to a Mac computer so progress is very slow ,

Maybe some of your codes may be helpful to my project as well.

I am still running the  Original project on my Windows 7 Computer a lot my codes are working you see more on my project  under cloud sensor.

Edited by Starlight 1
Link to comment
Share on other sites

My rain sensor Side of project had already been done it simply a set of LED lights on the side of the shed change colours to indicate the Changing weather conditions which make it easy for me to just close down the program until the sky conditions improve maybe I'll do more work on this later to make it more computerised.

Link to comment
Share on other sites

My rain sensor Side of project had already been done it simply a set of LED lights on the side of the shed change colours to indicate the Changing weather conditions which make it easy for me to just close down the program until the sky conditions improve maybe I'll do more work on this later to make it more computerised.

Well, because i am going to use a fully automated observatory, i need to be 100% sure of that my bits and pieces works, in case of rain etc.

I could use a led-based warning system, but that require my attention through the whole night, witch not is an option.

/Daniel

Link to comment
Share on other sites

I've done a bunch of ASCOM drivers over the years, and on the surface this one seems trivila to implement. 

Perhaps I'm missing something...

Do you really you just want to just connect to an Arduino over its USB/serial interface, ask for the cloud sensor/rain-sensor data, get the reply, make a decision based on a few user configurable thresholds, then set IsSafe() to return true/false?  If you need nothing else talking to the device (at the same time) it should be easy.

Link to comment
Share on other sites

I've done a bunch of ASCOM drivers over the years, and on the surface this one seems trivila to implement. 

Perhaps I'm missing something...

Do you really you just want to just connect to an Arduino over its USB/serial interface, ask for the cloud sensor/rain-sensor data, get the reply, make a decision based on a few user configurable thresholds, then set IsSafe() to return true/false?  If you need nothing else talking to the device (at the same time) it should be easy.

Yep, maybe even more simple, the arduino is sending just "IsSafe" or nothing at all (i think that is what ascom listens to?) 

I have been writing som more code to get the if statements to work;

If the temperature difference is greater than 21 degrees AND there is no rain - it will trigger this;

DS18B20  Temperature:	25.44	CelsiusMLX90614 Temperature:	51.24	CelsiusDELTA Temperature:	25.80	CelsiusRain sensor status:             Not RainingAscom Safety monitor status:    IsSafe

In all other cases, it will write nothing in the Ascom Safety monitor line, like in this case when there is no cloud (greater temp diff than 21 degrees, but a rain warning)

DS18B20  Temperature:	25.44	CelsiusMLX90614 Temperature:	46.82	CelsiusDELTA Temperature:	21.38	CelsiusRain sensor status:             Rain WarningAscom Safety monitor status:    

I will now work on the code to make the "IsSafe" command to be written first after a couple of minutes of temp-differenture, not just only one single temp diff measure.

Here is the code so far;

/*** This sketch reads three sensors:*  DS18B20 - Connected to D10*  MLX90614 - Connected to SCL-A5, SDA-A4*  Rain sensor conected to A0* It calculates the temperatures (DS18B20 and MLX90614)* DS18B20: http://playground.arduino.cc/Learning/OneWire* MLX90614: http://bildr.org/2011/02/mlx90614-arduino/*///get it here: http://www.pjrc.com/teensy/td_libs_OneWire.html#include <OneWire.h>//get it here: http://jump.to/fleury#include <i2cmaster.h>#include <SPI.h>// lowest and highest rain sensor readings:const int sensorMin = 0;     // sensor minimumconst int sensorMax = 1024;  // sensor maximumOneWire  ds(10);  // DS18B20 on Arduino pin 10byte ds18b20_addr[8];void setup(void) {  Serial.begin(19200);      init_DS18B20();  init_MLX90614();}void init_DS18B20(){  Serial.println("Initializing DS18B20 sensor...");  while( !ds.search(ds18b20_addr))   {    ds.reset_search();    delay(250);  }}void init_MLX90614(){  Serial.println("Initializing MLX90614 sensor...");  i2c_init(); //Initialise the i2c bus  //	PORTC = (1 << PORTC4) | (1 << PORTC5);//enable pullups if you use 5V sensors and don't have external pullups in the circuit}void loop(void) {  float ds18b20_celsius = read_DS18B20();    Serial.println();  Serial.print("DS18B20  Temperature:\t");  Serial.print(ds18b20_celsius);  Serial.println("\tCelsius");  float MLX90614_celsius = read_MLX90614();  Serial.print("MLX90614 Temperature:\t");  Serial.print(MLX90614_celsius);  Serial.println("\tCelsius");    float delta_celsius = abs(ds18b20_celsius - MLX90614_celsius);  Serial.print("DELTA Temperature:\t");  Serial.print(delta_celsius);  Serial.println("\tCelsius");     //Rain sensor    // read the sensor on analog A0:	int sensorReading = analogRead(A0);  // map the sensor range (four options):  // ex: 'long int map(long int, long int, long int, long int, long int)'	int range = map(sensorReading, sensorMin, sensorMax, 0, 3);  Serial.print("Rain sensor status:             ");  // range value:  switch (range) {     case 0:    // Sensor getting wet    Serial.println("Rain");    break; case 1:    // Sensor getting wet    Serial.println("Rain Warning");    break; case 2:    // Sensor dry - To shut this up delete the " Serial.println("Not Raining"); " below.    Serial.println("Not Raining");    break;  }  delay(1);  // delay between reads  //End rain sensor  Serial.print("Ascom Safety monitor status:    ");  if ((delta_celsius >21) && (range>1))     {  Serial.println("IsSafe");}  delay(1000);  }float read_DS18B20(){  byte i;  byte present = 0;  byte type_s;  byte data[12];  float celsius;  if (OneWire::crc8(ds18b20_addr, 7) != ds18b20_addr[7])   {    Serial.println("CRC is not valid!");    return -300.0f;  }  // the first ROM byte indicates which chip  switch (ds18b20_addr[0])   {  case 0x10:    type_s = 1;    break;  case 0x28:    type_s = 0;    break;  case 0x22:    type_s = 0;    break;  default:    return -301.0f;  }   ds.reset();  ds.select(ds18b20_addr);  ds.write(0x44, 1);        // start conversion, with parasite power on at the end  delay(1000);     // maybe 750ms is enough, maybe not  // we might do a ds.depower() here, but the reset will take care of it.  present = ds.reset();  ds.select(ds18b20_addr);      ds.write(0xBE);         // Read Scratchpad  //read 9 data bytes  for ( i = 0; i < 9; i++)   {    data[i] = ds.read();  }  // Convert the data to actual temperature  int16_t raw = (data[1] << 8) | data[0];  if (type_s)   {    raw = raw << 3; // 9 bit resolution default    if (data[7] == 0x10) {      // "count remain" gives full 12 bit resolution      raw = (raw & 0xFFF0) + 12 - data[6];    }  }   else   {    byte cfg = (data[4] & 0x60);    // at lower res, the low bits are undefined, so let's zero them    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms    //// default is 12 bit resolution, 750 ms conversion time  }  celsius = (float)raw / 16.0;  return celsius;}float read_MLX90614(){  int dev = 0x5A<<1;  int data_low = 0;  int data_high = 0;  int pec = 0;  i2c_start_wait(dev+I2C_WRITE);  i2c_write(0x07);  // read  i2c_rep_start(dev+I2C_READ);  data_low = i2c_readAck(); //Read 1 byte and then send ack  data_high = i2c_readAck(); //Read 1 byte and then send ack  pec = i2c_readNak();  i2c_stop();  //This converts high and low bytes together and processes temperature, MSB is a error bit and is ignored for temps  double tempFactor = 0.02; // 0.02 degrees per LSB (measurement resolution of the MLX90614)  double tempData = 0x0000; // zero out the data  int frac; // data past the decimal point  // This masks off the error bit of the high byte, then moves it left 8 bits and adds the low byte.  tempData = (double)(((data_high & 0x007F) << 8) + data_low);  tempData = (tempData * tempFactor)-0.01;  float celcius = tempData - 273.15;  return celcius;}

/Daniel

Edited by Corpze
Link to comment
Share on other sites

So... you're ok with nothing else connecting to the Arduino, just my ASCOM driver.

First thing I'd do is change the firmware over to a command/response system so the ASCOM driver and your firmware can have a simple conversation to hand the data over.

Howard

Link to comment
Share on other sites

Well, I can´t write software, or at least, i haven't done that before.

It might be better to write a software so you can change settings like sensitivity etc. but i lack the knowledge.

How does the driver send/recieves commands? I understand that the firmware i write to the hardware now sends only "IsSafe" when it isn't any clouds AND no rain, otherwise it sends nothing at all.

Is this a safe way to go?

/D

Link to comment
Share on other sites

Hmm, I am stuck in my coding, the problem is that i want to take continuous readings from the MLX90614 (ir/cloud sensor) and want to know the value for debugging etc. BUT to be able to average the calculations between the IR-sensor and the temp sensor (not the actual readings from the sensors) i have to take for instance 300 calculations (1 calculation per second is 5 minutes) This is to not trigger the roof being closed as soon a small little cirrus cloud sweeps pass, but if there is cloud adding up for about 5 minutes...

I don't know how to write this code...

excuse my bad english... hard to explain but i hope you get a hang of what i mean.

I don't want to average readings but the calculation below;

delta_celsius = abs(ds18b20_celsius - MLX90614_celsius)

and then print out the result, something like this (horrible code, but i think you know what i mean;

Serial.print("Ascom Safety monitor status:    ");  if ((delta_celsius 300/300 >21 ) && (range>1))          // 300 calculations divided by 300 to get the average     {  Serial.println("IsSafe");

If the sensor is read 1 time a second (or is it just the serial.print that is once a second?)

Link to comment
Share on other sites

I'll look that over in a little while... kind of burned out now.  I have a working ASCOM safety monitor (in C#) talking to a modified version of your firmware....

That  <i2cmaster.h> library is very squirmy.  Naturally, I can't really test the hardware attached and had to fake the readings from sensors.

Do you want me to add this stuff to my GitHub for easy download and collaboration?

Link to comment
Share on other sites

Don't worry, I have an automated observatory and cloud sensor hardware in the works here too... I'll need something very similar to this one of these days.

The modified firmware is here:

https://github.com/hjd1964/CloudSensorEvoPlus

Let me know if it works, note that the serial interface is set for 9600baud.

Commands must be sent to see the sensor values.  The Arduino serial monitor works fine for this.

:IN#

Firmware version

:IP#

Firmware name

:G1#

Get first temperature

:G2#

Get 2nd temperature

:G3#

Get differental

:GR#

Get rain sensor

Link to comment
Share on other sites

Hmm, I am stuck in my coding, the problem is that i want to take continuous readings from the MLX90614 (ir/cloud sensor) and want to know the value for debugging etc. BUT to be able to average the calculations between the IR-sensor and the temp sensor (not the actual readings from the sensors) i have to take for instance 300 calculations (1 calculation per second is 5 minutes) This is to not trigger the roof being closed as soon a small little cirrus cloud sweeps pass, but if there is cloud adding up for about 5 minutes...

I don't know how to write this code...

excuse my bad english... hard to explain but i hope you get a hang of what i mean.

I don't want to average readings but the calculation below;

delta_celsius = abs(ds18b20_celsius - MLX90614_celsius)

and then print out the result, something like this (horrible code, but i think you know what i mean;

Serial.print("Ascom Safety monitor status:    ");  if ((delta_celsius 300/300 >21 ) && (range>1))          // 300 calculations divided by 300 to get the average     {  Serial.println("IsSafe");

If the sensor is read 1 time a second (or is it just the serial.print that is once a second?)

It does sound like you want to average the delta (sky temperature) readings over a period of time. 

You could do either a true average or a moving average... the true average is memory and processor intensive.  The moving average much is easier and lighter weight:

avg_delta_celsius=(avg_delta_celsius*300.0+delta_celsius)/300.0;

This way, the current measurement only contributes 1/300th of the average, you'll need to experiment with exact values to get the behaviour you want. 

Link to comment
Share on other sites

Don't worry, I have an automated observatory and cloud sensor hardware in the works here too... I'll need something very similar to this one of these days.

The modified firmware is here:

https://github.com/hjd1964/CloudSensorEvoPlus

Let me know if it works, note that the serial interface is set for 9600baud.

Commands must be sent to see the sensor values.  The Arduino serial monitor works fine for this.

:IN#

Firmware version

:IP#

Firmware name

:G1#

Get first temperature

:G2#

Get 2nd temperature

:G3#

Get differental

:GR#

Get rain sensor

I loaded the new firmware, but when i try to compile, it get this;

CloudSensorEvoPlus.ino: In function 'void loop()':

CloudSensorEvoPlus:110: error: 'processCommands' was not declared in this scope
Do i have to run it together with the driver?

It does sound like you want to average the delta (sky temperature) readings over a period of time. 

You could do either a true average or a moving average... the true average is memory and processor intensive.  The moving average much is easier and lighter weight:

avg_delta_celsius=(avg_delta_celsius*300.0+delta_celsius)/300.0;

This way, the current measurement only contributes 1/300th of the average, you'll need to experiment with exact values to get the behaviour you want. 

Yes, that is exactly what i want to do, Sounds like moving average is the way to go.

I will look in to this more later on... getting late here in sweden right now, and clear skies for the first time in two weeks and my new DDM85 needs a polar align :D

/Daniel

Link to comment
Share on other sites

I loaded the new firmware, but when i try to compile, it get this;

CloudSensorEvoPlus.ino: In function 'void loop()':

CloudSensorEvoPlus:110: error: 'processCommands' was not declared in this scope
Do i have to run it together with the driver?
---------------
The compiler can't find the processCommands function, which is in the Command.ino file.  This file needs be in the same directory as the CloudSensorEvoPlus.ino file and should then be automatically found.  You might need to close and re-open the Arduino environment for it to be recognized though.
Link to comment
Share on other sites

Hrmmpffff.... cloudy again... at least the code worked and the Commands could be sent to the arduino and the data got received like it should!
Everything looks ok so far.

I'll check on that average later on :p

/D

Link to comment
Share on other sites

I have tried the new average function, I declared it as an int, don't know if thats the best way, how ever... didn't trigger IsSafe... need som sleep now :p

Here is the code i tried with.

Serial.print("Ascom Safety monitor status:    ");

  int avg_delta_celsius= (avg_delta_celsius*299.0+delta_celsius)/300.0;
  if ((avg_delta_celsius >21) && (range>1))
     {
  Serial.println("IsSafe");
Good Night :D
Link to comment
Share on other sites

That should be a float.

I added some monitoring code to the setup dialog so you can debug and reporting of that new average you're working on.  I'll throw together an installer tomorrow and give you a copy.

Here's what the setup dialog looks like now, this was live, connected to an Arduino Mega2560:

cse.jpg

Link to comment
Share on other sites

That looks awesome, The "Average Sky Temperature" should be "Average Delta Sky Temp", otherwise, it might get confusing, after all, it is the difference in temperature that are the most interesting bit.

I am sadly not having any luck with the;  float avg_delta_celsius= (avg_delta_celsius*14.0+delta_celsius)/15.0;  

(cut it down to 15 values so i didn't have to wait so long to test the code) Still not writing "IsSafe"

Do you think there is good to have the arduino write out "IsNotSafe" otherwise?

/Daniel

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. By using this site, you agree to our Terms of Use.