RANet Cloud and Lightning
Re: RANet Cloud and Lightning
No, the lightning can happen whenever you want. The minute we send the trigger, the receiver will create the lightning effect for 5 to 10s.
This will happen even if the lights are full brightness, because the lightning will be trigger based now. But you can control when you want to send the trigger. so you can set it to trigger only when there is a cloud and only in certain clouds and not all of them.
This will happen even if the lights are full brightness, because the lightning will be trigger based now. But you can control when you want to send the trigger. so you can set it to trigger only when there is a cloud and only in certain clouds and not all of them.
Roberto.
Re: RANet Cloud and Lightning
ahh then 5 to 10 seconds sounds good
Re: RANet Cloud and Lightning
It's already trigger based. The new version changes the mechanism of the trigger, but not the general principle of operation. The new version has a dedicated byte for the trigger, whereas the older one had the trigger hidden in one of the dimming channels.
The trigger is sent by the checkcloud function in the RA code. The receiver then generates a set of 1 to 4 flashes. The frequency of the trigger depends on the mode chosen.
There are variables in the checkcloud function that can be changed to adjust frequency of lightning, chance of lightning per cloud, etc.
Roberto's code is pretty much identical in the way the lightning is generated and the timing, which is what confuses me.
--Colin
The trigger is sent by the checkcloud function in the RA code. The receiver then generates a set of 1 to 4 flashes. The frequency of the trigger depends on the mode chosen.
There are variables in the checkcloud function that can be changed to adjust frequency of lightning, chance of lightning per cloud, etc.
Roberto's code is pretty much identical in the way the lightning is generated and the timing, which is what confuses me.
--Colin
Re: RANet Cloud and Lightning
Well I tried out my new bluetooth attachment and reloaded the controller code with the dev library and now instead channel 2 is flashing but not channel 1 video attached for the "flash".
response was still very slow but also stepped up and down instead of flashing
https://www.youtube.com/watch?v=eYNWTjKiiYs
response was still very slow but also stepped up and down instead of flashing
https://www.youtube.com/watch?v=eYNWTjKiiYs
Re: RANet Cloud and Lightning
the new library had another effect, after the storm was over channel 0 and channel 2 shut off completely.
Re: RANet Cloud and Lightning
The old RANet receiver code is incompatible with the new library.
Re: RANet Cloud and Lightning
Ok, went back to the other library for now. Just noticed something that may be of help.
Where you would expect the lighting to ramp up the whites it is actually flashing off then back on to the level called for in the cloud. At no point during any flash does the light ramp up, like it is working in reverse.
Where you would expect the lighting to ramp up the whites it is actually flashing off then back on to the level called for in the cloud. At no point during any flash does the light ramp up, like it is working in reverse.
Re: RANet Cloud and Lightning
I'll be off work in a few hours. I'll take a look at it. That does help.
Re: RANet Cloud and Lightning
In the latest receiver code posted you used a variable for the channels here
In the test code the channels are listed individually
Looking through attempting to understand why one would work but not the other. As you can see I am doing everything in my power to avoid studying for the bar exam I have to take in two weeks
Code: Select all
for (int n=1; n<3; n++)
{
int newdata=4095;
Wire.beginTransmission(0x40); // Address of the dimming expansion module
Wire.write(0x8+(4*n)); // 0x8 is channel 0, 0x12 is channel 1, etc. I'm using channel 1.
Wire.write(newdata&0xff); // Send the data 8 bits at a time. This sends the LSB
Wire.write(newdata>>8); // This sends the MSB
Wire.endTransmission();
}
Code: Select all
{
int a=random(5);
for (int i=0;i<a;i++)
{
newdata=4095;
Wire.beginTransmission(0x40);
Wire.write(0x8+(4*0));
Wire.write(newdata&0xff);
Wire.write(newdata>>8);
Wire.endTransmission();
Wire.beginTransmission(0x40);
Wire.write(0x8+(4*1));
Wire.write(newdata&0xff);
Wire.write(newdata>>8);
Wire.endTransmission();
Wire.beginTransmission(0x40);
Wire.write(0x8+(4*2));
Wire.write(newdata&0xff);
Wire.write(newdata>>8);
Wire.endTransmission();
delay(20+random(50));
newdata=0;
Wire.beginTransmission(0x40);
Wire.write(0x8+(4*0));
Wire.write(newdata&0xff);
Wire.write(newdata>>8);
Wire.endTransmission();
Wire.beginTransmission(0x40);
Wire.write(0x8+(4*1));
Wire.write(newdata&0xff);
Wire.write(newdata>>8);
Wire.endTransmission();
Wire.beginTransmission(0x40);
Wire.write(0x8+(4*2));
Wire.write(newdata&0xff);
Wire.write(newdata>>8);
Wire.endTransmission();
delay(30+random(20));
}
delay(random(1000));
}
Re: RANet Cloud and Lightning
Yeah, I thought about that. Try this.
Code: Select all
#include <Wire.h>
#include <avr/eeprom.h>
#define BLUE_LED 9
#define WHITE_LED 10
#define BLUE_INTENSITY 255
#define WHITE_INTENSITY 255
#define RANET_MAX_SIZE 64
#define DISCONNECT_TIMEOUT 2000
#define LastFallback0 100 // Memory location for fallback storage
#define RANet_Down 0
#define RANet_OK 1
byte Trigger=150; // Trigger value for lightning effect
byte TriggerChannel=1; // Channel to look for the trigger on
byte buffer_index;
byte buffer[128];
char buf[3];
byte bufint, bufsize;
byte RANetData[RANET_MAX_SIZE];
byte RANetCRC;
byte BlueChannel=0;
byte WhiteChannel=0;
byte RANet_Status=RANet_Down;
boolean cable_present=false;
unsigned long lastmillis=millis();
unsigned long lastcablecheck=millis();
void setup()
{
pinMode(BLUE_LED,OUTPUT);
pinMode(WHITE_LED,OUTPUT);
Serial.begin(57600);
Wire.onReceive(NULL);
Wire.onRequest(NULL);
Wire.begin();
for (int a=0;a<RANET_MAX_SIZE; a++) // Clear array
RANetData[a]=0;
Wire.beginTransmission(0x68);
Wire.write(0);
int a=Wire.endTransmission();
cable_present=(a==0);
// setup PCA9685 for data receive
// we need this to make sure it will work if connected ofter controller is booted, so we need to send it all the time.
Wire.beginTransmission(0x40);
Wire.write(0);
Wire.write(0xa1);
Wire.endTransmission();
}
void loop()
{
if (cable_present)
{
BlueChannel=100;
WhiteChannel=0;
analogWrite(WHITE_LED,WHITE_INTENSITY*WhiteChannel/100);
analogWrite(BLUE_LED,BLUE_INTENSITY*BlueChannel/100);
}
else
{
BlueChannel=0;
WhiteChannel=0;
while(Serial.available())
{
UpdateWhiteChannel();
char c = Serial.read(); // Read each incoming byte
buffer[buffer_index]=c; // store in the buffer array
if (c==10) // if line feed we analyze the payload
{
if (buffer_index>25) // only need to analyse if buffer_index is greater than 25, otherwise the payload is broken or corrupt
if (buffer_index==buffer[1]) // check if payload matches the length the controller sent
{
UpdateWhiteChannel();
RANetCRC=0;
for (int a=0; a<(buffer_index-2); a++) // calculate CRC
RANetCRC+=buffer[a];
UpdateWhiteChannel();
if (RANetCRC==buffer[buffer_index-2]) // if CRC matches
{
UpdateWhiteChannel();
for (int a=0; a<(buffer_index-2); a++) // Copy buffer to RANetData
RANetData[a]=buffer[a];
UpdateWhiteChannel();
lastmillis=millis();
// Serial.print(millis());
// Serial.print("\t");
// Serial.println(RANetData[2]);
for (int a=0;a<8;a++)
{
if (eeprom_read_byte((unsigned char *) LastFallback0+a)!=RANetData[10+a])
{
eeprom_write_byte((unsigned char *) LastFallback0+a, RANetData[10+a]);
}
Wire.beginTransmission(0x38+a);
Wire.write(~RANetData[2+a]);
Wire.endTransmission();
}
// Check for lightning trigger
if (RANetData[18+TriggerChannel] == Trigger) Lightning();
else // If the trigger has not been sent
{
for (int a=0;a<6;a++) // send along the data
{
int newdata=(int)(RANetData[18+a]*40.95);
Wire.beginTransmission(0x40);
Wire.write(0x8+(4*a));
Wire.write(newdata&0xff);
Wire.write(newdata>>8);
Wire.endTransmission();
}
}
UpdateWhiteChannel();
RANet_Status=RANet_OK;
}
}
buffer_index=255; // reset buffer index
}
UpdateWhiteChannel();
if (buffer_index++>=128) buffer_index=0; // increment index of buffer array. reset index if >=128
}
if (millis()-lastmillis>DISCONNECT_TIMEOUT)
{
lastmillis=millis();
// Serial.println("Disconnected");
// Serial.print(millis());
// Serial.print("\t");
// Serial.println(RANetData[10]);
for (int a=0;a<8;a++)
{
Wire.beginTransmission(0x38+a);
Wire.write(~eeprom_read_byte((unsigned char *) LastFallback0+a));
Wire.endTransmission();
}
RANet_Status=RANet_Down;
}
if (RANet_Status==RANet_Down)
{
BlueChannel=0;
WhiteChannel=millis()%2000<1000?0:100;
analogWrite(WHITE_LED,WHITE_INTENSITY*WhiteChannel/100);
analogWrite(BLUE_LED,BLUE_INTENSITY*BlueChannel/100);
}
}
}
void UpdateWhiteChannel()
{
WhiteChannel=sin(radians((millis()%7200)/40))*255;
BlueChannel=255-(sin(radians((millis()%7200)/40))*255);
analogWrite(WHITE_LED,WhiteChannel);
analogWrite(BLUE_LED,BlueChannel);
}
void Lightning()
{
int a=random(1,5); // Pick a number of consecutive flashes from 1 to 4.
for (int i=0; i<a; i++)
{
// Flash on
int newdata=4095;
Wire.beginTransmission(0x40); // Address of the dimming expansion module
Wire.write(0x8+(4*1)); // 0x8 is channel 0, 0x12 is channel 1, etc. I'm using channel 1.
Wire.write(newdata&0xff); // Send the data 8 bits at a time. This sends the LSB
Wire.write(newdata>>8); // This sends the MSB
Wire.endTransmission();
Wire.beginTransmission(0x40); // Address of the dimming expansion module
Wire.write(0x8+(4*2)); // 0x8 is channel 0, 0x12 is channel 1, etc. I'm using channel 1.
Wire.write(newdata&0xff); // Send the data 8 bits at a time. This sends the LSB
Wire.write(newdata>>8); // This sends the MSB
Wire.endTransmission();
int randy=random(20,80); // Random number for a delay
if (randy>71) randy=((randy-70)/2)*100; // Small chance of a longer delay
delay(randy); // Wait from 20 to 69 ms, or 100-400 ms
// Flash off
newdata=0;
Wire.beginTransmission(0x40); // Same as above
Wire.write(0x8+(4*1));
Wire.write(newdata&0xff);
Wire.write(newdata>>8);
Wire.endTransmission();
Wire.beginTransmission(0x40); // Same as above
Wire.write(0x8+(4*2));
Wire.write(newdata&0xff);
Wire.write(newdata>>8);
Wire.endTransmission();
delay(random(30,50)); // Wait from 30 to 49 ms
}
}
Last edited by cosmith71 on Sat Feb 07, 2015 7:39 pm, edited 1 time in total.
Re: RANet Cloud and Lightning
with the dev libraries? Im getting a compiling error with the original
Code: Select all
ketch_feb07b.cpp: In function 'void Lightning()':
sketch_feb07b:185: error: redeclaration of 'int newdata'
sketch_feb07b:166: error: 'int newdata' previously declared here
Re: RANet Cloud and Lightning
Dammit. It's been a long day.
I fixed it. Recopy and try again, with the regular, non-dev libraries.
--Colin
I fixed it. Recopy and try again, with the regular, non-dev libraries.
--Colin
Re: RANet Cloud and Lightning
still just channel 1 and with a flash off instead of ramping up
Re: RANet Cloud and Lightning
One more try for the night. This should flash all three channels.
Code: Select all
#include <Wire.h>
#include <avr/eeprom.h>
#define BLUE_LED 9
#define WHITE_LED 10
#define BLUE_INTENSITY 255
#define WHITE_INTENSITY 255
#define RANET_MAX_SIZE 64
#define DISCONNECT_TIMEOUT 2000
#define LastFallback0 100 // Memory location for fallback storage
#define RANet_Down 0
#define RANet_OK 1
byte Trigger=150; // Trigger value for lightning effect
byte TriggerChannel=1; // Channel to look for the trigger on
byte buffer_index;
byte buffer[128];
char buf[3];
byte bufint, bufsize;
byte RANetData[RANET_MAX_SIZE];
byte RANetCRC;
byte BlueChannel=0;
byte WhiteChannel=0;
byte RANet_Status=RANet_Down;
boolean cable_present=false;
unsigned long lastmillis=millis();
unsigned long lastcablecheck=millis();
void setup()
{
pinMode(BLUE_LED,OUTPUT);
pinMode(WHITE_LED,OUTPUT);
Serial.begin(57600);
Wire.onReceive(NULL);
Wire.onRequest(NULL);
Wire.begin();
for (int a=0;a<RANET_MAX_SIZE; a++) // Clear array
RANetData[a]=0;
Wire.beginTransmission(0x68);
Wire.write(0);
int a=Wire.endTransmission();
cable_present=(a==0);
// setup PCA9685 for data receive
// we need this to make sure it will work if connected ofter controller is booted, so we need to send it all the time.
Wire.beginTransmission(0x40);
Wire.write(0);
Wire.write(0xa1);
Wire.endTransmission();
}
void loop()
{
if (cable_present)
{
BlueChannel=100;
WhiteChannel=0;
analogWrite(WHITE_LED,WHITE_INTENSITY*WhiteChannel/100);
analogWrite(BLUE_LED,BLUE_INTENSITY*BlueChannel/100);
}
else
{
BlueChannel=0;
WhiteChannel=0;
while(Serial.available())
{
UpdateWhiteChannel();
char c = Serial.read(); // Read each incoming byte
buffer[buffer_index]=c; // store in the buffer array
if (c==10) // if line feed we analyze the payload
{
if (buffer_index>25) // only need to analyse if buffer_index is greater than 25, otherwise the payload is broken or corrupt
if (buffer_index==buffer[1]) // check if payload matches the length the controller sent
{
UpdateWhiteChannel();
RANetCRC=0;
for (int a=0; a<(buffer_index-2); a++) // calculate CRC
RANetCRC+=buffer[a];
UpdateWhiteChannel();
if (RANetCRC==buffer[buffer_index-2]) // if CRC matches
{
UpdateWhiteChannel();
for (int a=0; a<(buffer_index-2); a++) // Copy buffer to RANetData
RANetData[a]=buffer[a];
UpdateWhiteChannel();
lastmillis=millis();
// Serial.print(millis());
// Serial.print("\t");
// Serial.println(RANetData[2]);
for (int a=0;a<8;a++)
{
if (eeprom_read_byte((unsigned char *) LastFallback0+a)!=RANetData[10+a])
{
eeprom_write_byte((unsigned char *) LastFallback0+a, RANetData[10+a]);
}
Wire.beginTransmission(0x38+a);
Wire.write(~RANetData[2+a]);
Wire.endTransmission();
}
// Check for lightning trigger
if (RANetData[18+TriggerChannel] == Trigger) Lightning();
else // If the trigger has not been sent
{
for (int a=0;a<6;a++) // send along the data
{
int newdata=(int)(RANetData[18+a]*40.95);
Wire.beginTransmission(0x40);
Wire.write(0x8+(4*a));
Wire.write(newdata&0xff);
Wire.write(newdata>>8);
Wire.endTransmission();
}
}
UpdateWhiteChannel();
RANet_Status=RANet_OK;
}
}
buffer_index=255; // reset buffer index
}
UpdateWhiteChannel();
if (buffer_index++>=128) buffer_index=0; // increment index of buffer array. reset index if >=128
}
if (millis()-lastmillis>DISCONNECT_TIMEOUT)
{
lastmillis=millis();
// Serial.println("Disconnected");
// Serial.print(millis());
// Serial.print("\t");
// Serial.println(RANetData[10]);
for (int a=0;a<8;a++)
{
Wire.beginTransmission(0x38+a);
Wire.write(~eeprom_read_byte((unsigned char *) LastFallback0+a));
Wire.endTransmission();
}
RANet_Status=RANet_Down;
}
if (RANet_Status==RANet_Down)
{
BlueChannel=0;
WhiteChannel=millis()%2000<1000?0:100;
analogWrite(WHITE_LED,WHITE_INTENSITY*WhiteChannel/100);
analogWrite(BLUE_LED,BLUE_INTENSITY*BlueChannel/100);
}
}
}
void UpdateWhiteChannel()
{
WhiteChannel=sin(radians((millis()%7200)/40))*255;
BlueChannel=255-(sin(radians((millis()%7200)/40))*255);
analogWrite(WHITE_LED,WhiteChannel);
analogWrite(BLUE_LED,BlueChannel);
}
void Lightning()
{
int a=random(5);
for (int i=0;i<a;i++)
{
int newdata=4095;
Wire.beginTransmission(0x40);
Wire.write(0x8+(4*0));
Wire.write(newdata&0xff);
Wire.write(newdata>>8);
Wire.endTransmission();
Wire.beginTransmission(0x40);
Wire.write(0x8+(4*1));
Wire.write(newdata&0xff);
Wire.write(newdata>>8);
Wire.endTransmission();
Wire.beginTransmission(0x40);
Wire.write(0x8+(4*2));
Wire.write(newdata&0xff);
Wire.write(newdata>>8);
Wire.endTransmission();
delay(20+random(50));
newdata=0;
Wire.beginTransmission(0x40);
Wire.write(0x8+(4*0));
Wire.write(newdata&0xff);
Wire.write(newdata>>8);
Wire.endTransmission();
Wire.beginTransmission(0x40);
Wire.write(0x8+(4*1));
Wire.write(newdata&0xff);
Wire.write(newdata>>8);
Wire.endTransmission();
Wire.beginTransmission(0x40);
Wire.write(0x8+(4*2));
Wire.write(newdata&0xff);
Wire.write(newdata>>8);
Wire.endTransmission();
delay(30+random(20));
}
}
Re: RANet Cloud and Lightning
and it still only flashes channel one
Re: RANet Cloud and Lightning
Ok if I change the trigger to be sent on channel 2 only channel 2 flashes
No change on the effect still not ramping up.
No change on the effect still not ramping up.
Re: RANet Cloud and Lightning
Hmmm. Give me a couple of days (one more 12 hour shift today and then some time off).
--Colin
--Colin
Re: RANet Cloud and Lightning
Lets try this. Use the dev libraries.
On the RA:
On the receiver module:
Note that this one doesn't necessarily go to black. You should have (fast) flashes that return to the previous white channel values.
On the RA:
Code: Select all
#define NUMBERS_8x16
#define FONT_8x8
#include <SoftwareSerial.h>
#include <ReefAngel_Features.h>
#include <Globals.h>
#include <RA_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <InternalEEPROM.h>
#include <RA_NokiaLCD.h>
#include <RA_ATO.h>
#include <RA_Joystick.h>
#include <LED.h>
#include <RA_TempSensor.h>
#include <Relay.h>
#include <RA_PWM.h>
#include <Timer.h>
#include <Memory.h>
#include <InternalEEPROM.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <Salinity.h>
#include <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <PH.h>
#include <WaterLevel.h>
#include <Humidity.h>
#include <DCPump.h>
#include <ReefAngel.h>
////// Place global variable code below here
byte DaylightPWMValue=0; // For cloud code
boolean FireInTheHole=false; // True if trigger has been sent
byte TriggerChannel=1; // Dimming expansion channel to look for lightning trigger
byte Trigger=150; // Value sent to RANet Dimming module to trigger lightning strikes
void DrawCustomMain()
{
byte x = 6;
byte y = 2;
byte t;
char text[7];
//static byte vtechmode=0;
// *********** CHANGE TEMP READOUT COLOR DEPENDENT ON CHILLER STATUS ***********
int TempColor; // Color for drawing temperature
boolean FanOn = ReefAngel.Relay.Status(Port8); // Get the status of the Chiller relay
if (FanOn)
{
TempColor = COLOR_RED; // Red text, too warm, chiller is on
}
if (!FanOn)
{
TempColor = COLOR_GREEN; // Green text, no chiller on
}
// ***********************************************************************************
ReefAngel.LCD.DrawDate(6, 2);
ReefAngel.LCD.Clear(COLOR_BLACK, 1, 11, 132, 11);
pingSerial();
ReefAngel.LCD.DrawLargeText(3,255,8,14,"Redneck Reefin!", Font8x8);
ReefAngel.LCD.DrawLargeText(3,255,8,55,"Jason & Sarah's", Font8x8);
ReefAngel.LCD.DrawLargeText(3,255,32,64,"Money Pit", Font8x8);
pingSerial();
ReefAngel.LCD.DrawText(COLOR_RED,255, 6, 88, "--------------------");
ReefAngel.LCD.DrawText(COLOR_RED,255, 2, 93, "|");
ReefAngel.LCD.DrawText(COLOR_RED,255, 2, 103, "|");
ReefAngel.LCD.DrawText(COLOR_RED,255, 2, 113, "|");
ReefAngel.LCD.DrawText(COLOR_RED,255, 2, 123, "|");
ReefAngel.LCD.DrawText(COLOR_RED,255, 126, 93, "|");
ReefAngel.LCD.DrawText(COLOR_RED,255, 126, 103, "|");
ReefAngel.LCD.DrawText(COLOR_RED,255, 126, 113, "|");
ReefAngel.LCD.DrawText(COLOR_RED,255, 126, 123, "|");
ReefAngel.LCD.DrawLargeText(0,255,8,25,"TANK", Font8x8);
ConvertNumToString(text, ReefAngel.Params.Temp[T3_PROBE], 10);
ReefAngel.LCD.DrawLargeText(TempColor, 255, 42, 25, text, Font8x8);
pingSerial();
ReefAngel.LCD.DrawLargeText(0,255,8,35,"HOOD", Font8x8);
ConvertNumToString(text, ReefAngel.Params.Temp[T1_PROBE], 10);
ReefAngel.LCD.DrawLargeText(153, 255, 42, 35, text, Font8x8);
pingSerial();
ReefAngel.LCD.DrawLargeText(0,255,8,45,"ROOM", Font8x8);
ConvertNumToString(text, ReefAngel.Params.Temp[T2_PROBE], 10);
ReefAngel.LCD.DrawLargeText(66, 255, 42, 45, text, Font8x8);
ReefAngel.LCD.DrawText(0,255,100,25,"pH");
ConvertNumToString(text, ReefAngel.Params.PH, 100);
ReefAngel.LCD.DrawLargeText(COLOR_BLACK, 255, 85, 35, text, Num8x16);
pingSerial();
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox(12, 75, TempRelay);
pingSerial();
ReefAngel.LCD.Clear(255,46,96,70,104);
ReefAngel.LCD.Clear(255,106,96,132,104);
ReefAngel.LCD.DrawText(0,255,8,96, "White=");
ReefAngel.LCD.DrawText(197,255,46,96, ReefAngel.PWM.GetChannelValue(1));
//ReefAngel.PWM.GetDaylightValue()),
pingSerial();
ReefAngel.LCD.DrawText(0,255,72,96, "Blue=");
ReefAngel.LCD.DrawText(3,255,106,96, ReefAngel.PWM.GetChannelValue(0));
//ReefAngel.PWM.GetActinicValue());
}
void DrawCustomGraph()
{
}
////// Place global variable code above here
void setup()
{
// This must be the first line
ReefAngel.Init(); //Initialize controller
ReefAngel.Use2014Screen(); // Let's use 2014 Screen
ReefAngel.AddWaterLevelExpansion(); // Water Level Expansion Module
ReefAngel.AddRANet(); // Support for RANet wireless accessories
// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = Port4Bit | Port5Bit | Port6Bit;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port1Bit | Port5Bit | Port6Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port3Bit;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = 0;
// Use T3 probe as temperature and overheat functions
ReefAngel.TempProbe = T3_PROBE;
ReefAngel.OverheatProbe = T3_PROBE;
// Ports that are always on
ReefAngel.Relay.On( Port2 );
ReefAngel.Relay.On( Port3 );
ReefAngel.Relay.On( Port4 );
ReefAngel.Relay.On( Port7 );
////// Place additional initialization code below here
////// Place additional initialization code above here
}
void loop()
{
ReefAngel.SingleATOLow( Port1 );
ReefAngel.WavemakerRandom( Port5,30,100 );
ReefAngel.WavemakerRandom( Port6,30,100 );
ReefAngel.StandardFan( Port8 );
////// Place your custom code below here
// Cloud/lightning lighting control
FireInTheHole=false;
ReefAngel.PWM.SetChannel( 0, PWMParabola(9,30,23,00,5,100,5) ); // Set actinic channel
DaylightPWMValue=PWMParabola(10,30,22,0,0,100,0);
CheckCloud(); // Check to see if it's time for a cloud/lightning
if (!FireInTheHole)
{
ReefAngel.PWM.SetChannel(1,DaylightPWMValue); // Whites are on channel 1
ReefAngel.PWM.SetChannel(2,DaylightPWMValue); // and channel 2
}
////// Place your custom code above here
// This should always be the last line
ReefAngel.Portal( "jegillis" );
ReefAngel.ShowInterface();
}
// Random Cloud/Thunderstorm effects function
void CheckCloud()
{
// ------------------------------------------------------------
// Change the values below to customize your cloud/storm effect
// Frequency in days based on the day of the month - number 2 means every 2 days, for example (day 2,4,6 etc)
// For testing purposes, you can use 1 and cause the cloud to occur everyday
#define Clouds_Every_X_Days 1
// Percentage chance of a cloud happening today
// For testing purposes, you can use 100 and cause the cloud to have 100% chance of happening
#define Cloud_Chance_per_Day 100
// Minimum number of minutes for cloud duration. Don't use max duration of less than 6
#define Min_Cloud_Duration 7
// Maximum number of minutes for the cloud duration. Don't use max duration of more than 255
#define Max_Cloud_Duration 15
// Minimum number of clouds that can happen per day
#define Min_Clouds_per_Day 3
// Maximum number of clouds that can happen per day
#define Max_Clouds_per_Day 4
// Only start the cloud effect after this setting
// In this example, start cloud after noon
#define Start_Cloud_After NumMins(12,00)
// Always end the cloud effect before this setting
// In this example, end cloud before 9:00pm
#define End_Cloud_Before NumMins(21,00)
// Percentage chance of a lightning happen for every cloud
// For testing purposes, you can use 100 and cause the lightning to have 100% chance of happening
#define Lightning_Change_per_Cloud 100
// Note: Make sure to choose correct values that will work within your PWMSLope settings.
// For example, in our case, we could have a max of 5 clouds per day and they could last for 50 minutes.
// Which could mean 250 minutes of clouds. We need to make sure the PWMSlope can accomodate 250 minutes of effects or unforseen resuls could happen.
// Also, make sure that you can fit double those minutes between Start_Cloud_After and End_Cloud_Before.
// In our example, we have 510 minutes between Start_Cloud_After and End_Cloud_Before, so double the 250 minutes (or 500 minutes) can fit in that 510 minutes window.
// It's a tight fit, but it did.
//#define printdebug // Uncomment this for debug print on Serial Monitor window
#define forcecloudcalculation // Uncomment this to force the cloud calculation to happen in the boot process.
// Add Random Lightning modes
#define Calm 0 // No lightning
#define Slow 1 // 5 seconds of slow lightning in the middle of a cloud for ELN style (slow response) drivers
#define Fast 2 // 5 seconds of fast lightning in the middle of a cloud for LDD style (fast response) drivers
#define Mega 3 // Lightning throughout the cloud, higher chance as it gets darker
#define Mega2 4 // Like Mega, but with more lightning
// Set which modes you want to use
// Example: { Slow, Fast, Mega, Mega2 } to randomize all four modes.
// { Mega2 } for just Mega2. { Mega, Mega, Fast} for Mega and Fast, with twice the chance of Mega.
byte LightningModes[] = {Mega};
// Change the values above to customize your cloud/storm effect
// ------------------------------------------------------------
// Do not change anything below here
static byte cloudchance=255;
static byte cloudduration=0;
static int cloudstart=0;
static byte numclouds=0;
static byte lightningchance=0;
static byte cloudindex=0;
static byte lightningstatus=0;
static int LastNumMins=0;
static byte lightningMode=0;
static boolean chooseLightning=true;
static time_t DelayCounter=millis(); // Variable for lightning timing.
static int DelayTime=random(1000); // Variable for lightning timimg.
// Every day at midnight, we check for chance of cloud happening today
if (hour()==0 && minute()==0 && second()==0) cloudchance=255;
#ifdef forcecloudcalculation
if (cloudchance==255)
#else
if (hour()==0 && minute()==0 && second()==1 && cloudchance==255)
#endif
{
randomSeed(millis()); // Seed the random number generator
//Pick a random number between 0 and 99
cloudchance=random(100);
// if picked number is greater than Cloud_Chance_per_Day, we will not have clouds today
if (cloudchance>Cloud_Chance_per_Day) cloudchance=0;
// Check if today is day for clouds.
if ((day()%Clouds_Every_X_Days)!=0) cloudchance=0;
// If we have cloud today
if (cloudchance)
{
// pick a random number for number of clouds between Min_Clouds_per_Day and Max_Clouds_per_Day
numclouds=random(Min_Clouds_per_Day,Max_Clouds_per_Day);
// pick the time that the first cloud will start
// the range is calculated between Start_Cloud_After and the even distribuition of clouds on this day.
cloudstart=random(Start_Cloud_After,Start_Cloud_After+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));
// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
// Now that we have all the parameters for the cloud, let's create the effect
if (cloudchance)
{
//is it time for cloud yet?
if (NumMins(hour(),minute())>=cloudstart && NumMins(hour(),minute())<(cloudstart+cloudduration))
{
DaylightPWMValue=ReversePWMSlope(cloudstart,cloudstart+cloudduration,DaylightPWMValue,5,180);
if (chooseLightning)
{
lightningMode=LightningModes[random(100)%sizeof(LightningModes)];
chooseLightning=false;
}
switch (lightningMode)
{
case Calm:
break;
case Mega:
// Lightning chance from beginning of cloud through the end. Chance increases with darkness of cloud.
if (lightningchance && random(ReversePWMSlope(cloudstart,cloudstart+cloudduration,100,0,180))<1 && (millis()-DelayCounter)>DelayTime)
{
// Send the trigger
WriteTrigger();
DelayCounter=millis(); // If we just had a round of flashes, then lets put in a longer delay
DelayTime=random(1000); // of up to a second for dramatic effect before we do another round.
}
break;
case Mega2:
// Higher lightning chance from beginning of cloud through the end. Chance increases with darkness of cloud.
if (lightningchance && random(ReversePWMSlope(cloudstart,cloudstart+cloudduration,100,0,180))<2)
{
WriteTrigger();
}
break;
case Fast:
// 5 seconds of lightning in the middle of the cloud
if (lightningchance && (NumMins(hour(),minute())==(cloudstart+(cloudduration/2))) && second()<5 && (millis()-DelayCounter)>DelayTime)
{
WriteTrigger();
DelayCounter=millis(); // If we just had a round of flashes, then lets put in a longer delay
DelayTime=random(1000); // of up to a second for dramatic effect before we do another round.
}
break;
case Slow:
// Slow lightning for 5 seconds in the middle of the cloud. Suitable for slower ELN style drivers
if (lightningchance && (NumMins(hour(),minute())==(cloudstart+(cloudduration/2))) && second()<5)
{
if (random(100)<20) lightningstatus=1;
else lightningstatus=0;
if (lightningstatus)
{
DaylightPWMValue=100;
}
else
{
DaylightPWMValue=0;
}
delay(1);
}
break;
default:
break;
}
}
else
{
chooseLightning=true; // Reset the flag to choose a new lightning type
}
if (NumMins(hour(),minute())>(cloudstart+cloudduration))
{
cloudindex++;
if (cloudindex < numclouds)
{
cloudstart=random(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2),(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2))+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));
// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
}
// Write the times of the next cloud, next lightning, and cloud duration to the screen and into some customvars for the Portal.
if (LastNumMins!=NumMins(hour(),minute()))
{
LastNumMins=NumMins(hour(),minute());
ReefAngel.LCD.Clear(255,0,120,132,132);
ReefAngel.LCD.DrawText(0,255,85,110,"Length");
ReefAngel.LCD.DrawText(0,255,11,110,"Cloud");
ReefAngel.LCD.DrawText(0,255,11,120,"00:00");
ReefAngel.LCD.DrawText(0,255,51,110,"Storm");
ReefAngel.LCD.DrawText(0,255,51,120,"00:00");
if (cloudchance && (NumMins(hour(),minute())<cloudstart))
{
int x=0;
if ((cloudstart/60)>=10) x=11;
else x=17;
ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart/60));
ReefAngel.CustomVar[3]=cloudstart/60; // Write the hour of the next cloud to custom variable for Portal reporting
if ((cloudstart%60)>=10) x=29;
else x=35;
ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart%60));
ReefAngel.CustomVar[4]=cloudstart%60; // Write the minute of the next cloud to custom variable for Portal reporting
}
ReefAngel.LCD.DrawText(0,255,90,120,cloudduration);
ReefAngel.CustomVar[7]=(cloudduration); // Put the duration of the next cloud in a custom var for the portal
if (lightningchance)
{
int x=0;
if (((cloudstart+(cloudduration/2))/60)>=10) x=51;
else x=57;
ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))/60));
ReefAngel.CustomVar[5]=(cloudstart+(cloudduration/2))/60; // Write the hour of the next lightning to a custom variable for the Portal
if (((cloudstart+(cloudduration/2))%60)>=10) x=69;
else x=75;
ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))%60)); // Write the minute of the next lightning to a custom variable for the Portal
ReefAngel.CustomVar[6]=(cloudstart+(cloudduration/2))%60;
}
}
}
byte ReversePWMSlope(long cstart,long cend,byte PWMStart,byte PWMEnd, byte clength)
{
long n=elapsedSecsToday(now());
cstart*=60;
cend*=60;
if (n<cstart) return PWMStart;
if (n>=cstart && n<=(cstart+clength)) return map(n,cstart,cstart+clength,PWMStart,PWMEnd);
if (n>(cstart+clength) && n<(cend-clength)) return PWMEnd;
if (n>=(cend-clength) && n<=cend) return map(n,cend-clength,cend,PWMEnd,PWMStart);
if (n>cend) return PWMStart;
}
void WriteTrigger()
{
FireInTheHole = true;
ReefAngel.RANetTrigger(1);
//ReefAngel.PWM.SetChannel(TriggerChannel, Trigger);
}
Code: Select all
#include <Wire.h>
#include <avr/eeprom.h>
#define BLUE_LED 9
#define WHITE_LED 10
#define BLUE_INTENSITY 255
#define WHITE_INTENSITY 255
#define RANET_MAX_SIZE 68
#define DISCONNECT_TIMEOUT 2000
#define LastFallback0 100 // Memory location for fallback storage
#define RANet_Down 0
#define RANet_OK 1
#define LIGHTNING 1 // Trigger value for lightning strike
#define TRIGGER 62 // Position in payload of trigger byte
byte buffer_index;
byte buffer[128];
char buf[3];
byte bufint, bufsize;
byte RANetData[RANET_MAX_SIZE];
byte RANetCRC;
byte BlueChannel=0;
byte WhiteChannel=0;
byte RANet_Status=RANet_Down;
boolean cable_present=false;
unsigned long lastmillis=millis();
unsigned long lastcablecheck=millis();
void setup()
{
pinMode(BLUE_LED,OUTPUT);
pinMode(WHITE_LED,OUTPUT);
Serial.begin(57600);
Wire.onReceive(NULL);
Wire.onRequest(NULL);
Wire.begin();
for (int a=0;a<RANET_MAX_SIZE; a++) // Clear array
RANetData[a]=0;
Wire.beginTransmission(0x68);
Wire.write(0);
int a=Wire.endTransmission();
cable_present=(a==0);
// setup PCA9685 for data receive
// we need this to make sure it will work if connected ofter controller is booted, so we need to send it all the time.
Wire.beginTransmission(0x40);
Wire.write(0);
Wire.write(0xa1);
Wire.endTransmission();
}
void loop()
{
if (cable_present)
{
BlueChannel=100;
WhiteChannel=0;
analogWrite(WHITE_LED,WHITE_INTENSITY*WhiteChannel/100);
analogWrite(BLUE_LED,BLUE_INTENSITY*BlueChannel/100);
}
else
{
BlueChannel=0;
WhiteChannel=0;
while(Serial.available())
{
UpdateWhiteChannel();
char c = Serial.read(); // Read each incoming byte
buffer[buffer_index]=c; // store in the buffer array
if (c==10) // if line feed we analyze the payload
{
if (buffer_index>25) // only need to analyse if buffer_index is greater than 25, otherwise the payload is broken or corrupt
if (buffer_index==buffer[1]) // check if payload matches the length the controller sent
{
UpdateWhiteChannel();
RANetCRC=0;
for (int a=0; a<(buffer_index-2); a++) // calculate CRC
RANetCRC+=buffer[a];
UpdateWhiteChannel();
if (RANetCRC==buffer[buffer_index-2]) // if CRC matches
{
UpdateWhiteChannel();
for (int a=0; a<(buffer_index-2); a++) // Copy buffer to RANetData
RANetData[a]=buffer[a];
UpdateWhiteChannel();
lastmillis=millis();
// Serial.print(millis());
// Serial.print("\t");
// Serial.println(RANetData[2]);
for (int a=0;a<8;a++)
{
if (eeprom_read_byte((unsigned char *) LastFallback0+a)!=RANetData[10+a])
{
eeprom_write_byte((unsigned char *) LastFallback0+a, RANetData[10+a]);
}
Wire.beginTransmission(0x38+a);
Wire.write(~RANetData[2+a]);
Wire.endTransmission();
}
for (int a=0;a<12;a=a+2) // Step through the 12 bytes of dimming data
{
byte newdata=(RANetData[18+a]); //LSB
byte newdata1=(RANetData[18+a+1]); //MSB
Wire.beginTransmission(0x40);
Wire.write(0x8+(4*(a/2))); // Channels 0 through 5
Wire.write(newdata); // Write LSB
Wire.write(newdata1); // Write MSB
Wire.endTransmission();
}
UpdateWhiteChannel();
RANet_Status=RANet_OK;
}
}
buffer_index=255; // reset buffer index
}
UpdateWhiteChannel();
if (buffer_index++>=128) buffer_index=0; // increment index of buffer array. reset index if >=128
}
if (millis()-lastmillis>DISCONNECT_TIMEOUT)
{
lastmillis=millis();
// Serial.println("Disconnected");
// Serial.print(millis());
// Serial.print("\t");
// Serial.println(RANetData[10]);
for (int a=0;a<8;a++)
{
Wire.beginTransmission(0x38+a);
Wire.write(~eeprom_read_byte((unsigned char *) LastFallback0+a));
Wire.endTransmission();
}
RANet_Status=RANet_Down;
}
if (RANet_Status==RANet_Down)
{
BlueChannel=0;
WhiteChannel=millis()%2000<1000?0:100;
analogWrite(WHITE_LED,WHITE_INTENSITY*WhiteChannel/100);
analogWrite(BLUE_LED,BLUE_INTENSITY*BlueChannel/100);
}
}
if (RANetData[TRIGGER]==LIGHTNING) Lightning(); // Look for lightning trigger
RANetData[TRIGGER]=0; // Clear trigger byte.
}
void UpdateWhiteChannel()
{
WhiteChannel=sin(radians((millis()%7200)/40))*255;
BlueChannel=255-(sin(radians((millis()%7200)/40))*255);
analogWrite(WHITE_LED,WhiteChannel);
analogWrite(BLUE_LED,BlueChannel);
}
void Lightning()
{
int a=random(1,5); // Pick a number of consecutive flashes from 1 to 4.
for (int i=0; i<a; i++)
{
// Flash on
int newdata=4095;
Wire.beginTransmission(0x40); // Address of the dimming expansion module
Wire.write(0x8+(4*1)); // 0x8 is channel 0, 0x12 is channel 1, etc. I'm using channel 1.
Wire.write(newdata&0xff); // Send the data 8 bits at a time. This sends the LSB
Wire.write(newdata>>8); // This sends the MSB
Wire.endTransmission();
Wire.beginTransmission(0x40); // Address of the dimming expansion module
Wire.write(0x8+(4*2)); // 0x8 is channel 0, 0x12 is channel 1, etc. I'm using channel 1.
Wire.write(newdata&0xff); // Send the data 8 bits at a time. This sends the LSB
Wire.write(newdata>>8); // This sends the MSB
Wire.endTransmission();
int randy=random(20,80); // Random number for a delay
if (randy>71) randy=((randy-70)/2)*100; // Small chance of a longer delay
delay(randy); // Wait from 20 to 69 ms, or 100-400 ms
// Flash off
Wire.beginTransmission(0x40); // Same as above
Wire.write(0x8+(4*1));
Wire.write(RANetData[20]); // Return to previous value
Wire.write(RANetData[21]);
Wire.endTransmission();
Wire.beginTransmission(0x40); // Same as above
Wire.write(0x8+(4*2));
Wire.write(RANetData[22]); // Return to previous value
Wire.write(RANetData[23]);
Wire.endTransmission();
delay(random(30,50)); // Wait from 30 to 49 ms
}
}
Re: RANet Cloud and Lightning
It's working!!
video to follow after I get my youtube app to listen to me
video to follow after I get my youtube app to listen to me
Re: RANet Cloud and Lightning
Awesome!
I still don't know what was wrong. Had to be something interfering with the trigger on channel 1. The new way is better anyway.
--Colin
I still don't know what was wrong. Had to be something interfering with the trigger on channel 1. The new way is better anyway.
--Colin