Navigation

    • Register
    • Login
    • OpenHardware.io
    • Categories
    • Recent
    • Tags
    • Popular
    1. Home
    2. stedew
    3. Posts
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups

    Posts made by stedew

    • RE: Help needed - SSR switch / SCR dimmer

      @ksga
      well i suggest you use google for this (the trafo). Also your link provide schema and code not so bad as a start. also there is a module (the Bluetooth classs) that set the power output from a literal in %. This is exactly what you need to bind it to Mysensor lib...
      this is what i found on ebay Example link
      This trafo does not provide much power but it is small and maybe sufficiënt for powering the arduino.
      There is one catch when using a trafo : it introduce a phase shift so you must provide e methode (i believe a fix constant will do in most cases ) to trim the "offset" of the zero crossing.
      As i am not a specialist on mysensors internal structure but for a atmega328p (uno) TCCR1A is used inseverall places ,for analog write Altsoftserial (RS485) etc. So you must be sure not to re-use the timer it will behave strange. Same is for the attachInterrupt function it is used in hwSleep function. As there are only 2 HW irq's you must choose the "right" one in most designs i believe irq 1 is used for the NRF24l01 /RFM69 so choose the other one on your mcu . For all these reasons i believe it will take many hours off testing to get the dimmer "glitch" free.
      I believe for this resons it is better to offload the mcu and use a dedicated chip/mcu when you want to use Mysensors in your dimmer.

      posted in General Discussion
      stedew
      stedew
    • RE: Help needed - SSR switch / SCR dimmer

      @ksga
      idd the bridge is not needed because the H1AA1 has two antiparrallel diodes.
      As i said before the heat is a function I³*R. So yes, these resistors will get very hot (1W consumption @ 240V in total) It is ilmho not a good idea to use it like this given the fact that you get a few resistors in your circuit that always consume 1W even when the dimmer is off (and the resistors get very hot when you use a 1/2w type)
      Yust imagine you consume 8760W every year yust to know the zero crossing..

      posted in General Discussion
      stedew
      stedew
    • RE: Help needed - SSR switch / SCR dimmer

      @ksga
      For the R1 R2 it is easy P = I² * R so for 240v rms this gives 8mA² * 30000 gives 1.92W! this wil give you a constant energy loss off 2W only to know the zero crossing (even when the light is out). Keep the old dimmer with the filament bulbs you will save energy 😃
      Possible the circuit is designed for 120VAC then you still need at least 1/2watt resistor (and 1W powerloss)
      When you google a little i find combinations that use a transformer for the zero crossing.
      Also the circuit here on instructables can help you
      integrate this in the switch example is not a real good idea. Build the code for the zero crossing and dimming (firing triac) preferable in a seperate module /code block without the mysensors overhead. maybe you find some clues where you got the schema.
      When you can succesfully dim on/off the lamp with your code then you can start thinking to glue it on the Mysensor lib(s)
      I didn't search the forum here but i can imagine that building a interrupt driven zero crossing dimmer is a real challence. Particulary when it has to co-operate with the mysensor library...
      I hope this helps
      Regards ,
      Stefan

      posted in General Discussion
      stedew
      stedew
    • RE: Alternative to ArduinoIDE

      @andrew
      Hello Andrew, as Anticimex already answered also other IDE's are possible (Atmel Studio with a arduino plugin seems to work) Atom, and others I use the Eclipse + plugin solution and are happy with it. It is really a powerfull solution with many configuration options. I had a few discussions with the maintainer of sloeber (Jantje) and in general i made a few observations that summerize yours: lsee discussions on github
      The problem for cpp is that you have to declare the prototypes because you lose the confort from the ino suffix.
      Regards ,
      Stefan

      posted in General Discussion
      stedew
      stedew
    • RE: Esp8266 with wifi off

      @emc2

      Tnx spot on 👍

      Before i measure 88mA and now ~ 30mA. In reality the profit (% saving) will be even higher. The test setup is with all node mcu hardware so there will definitly be a higher gain with a "bare" esp.
      As for some may ask: why use a esp (nodeMCU) as a arduino?
      -"Solid" Integrated 3v3 regulator
      -Good RF design(shielding)
      -USB RS232 interface
      -High processing power (if needed).

      -I could not get the wifi gateway rock solid (compared to the RS232) .
      From the moment domoticz disconnect (or the ESP lost connection) there was no communication anymore without an intervention to domoticz.

      Regards,
      Stefan.

      posted in General Discussion
      stedew
      stedew
    • Esp8266 with wifi off

      Hello,
      I have a small question and maybe someone else already knows the answer.
      For testing i want to use a esp8266 (esp12 /nodemcu board) with a nrf24L01+) as a GW (serial).
      I have this working but i want to shut down the WIFI completely what instruction i have to use for this?

          wifi_set_sleep_type(MODEM_SLEEP_T);
      	delay(1);
          system_deep_sleep_set_option(MODEM_SLEEP_T);```
       
      

      I don't know exactly and also while testing i was pinging the wrong ip so i got a little confused 😉
      What i basicly want to do is use the esp as a high performance GW/node.
      So any suggest are welcome.
      regards,
      Stefan.

      posted in General Discussion
      stedew
      stedew
    • RE: RS485 Speed and different routing possible?

      haha,
      I knew you gonne hijack this thread
      As you answered the first question (more or less)
      i was looking for a good test rig
      long distance transmission line

      I yust have to re-read the specs off the ADM isolator i think 😃
      So there is no possibility to route from node to node pitty.
      Tnx for the answer anyway i will try the higher speed setting (57K6 or so)
      Btw good write up about the RS485 setup on the home page it will defenetly speed up things (as i spend a few hours wit wrong setup)
      Regards,
      Stefan.

      posted in General Discussion
      stedew
      stedew
    • RS485 Speed and different routing possible?

      Hello someone tested a higher speed setting for the (new) RS485 communication in MS2.0.?
      I think that 9600baud is really slow. That being sayed i have to admit it works like a charm.
      -So when someone can confirm that this works also with long(er) lines and higher speed i would like to know.
      In my setup i use on one side (GW + RPI) a ADM2483 (isolator) so that i have a galvanic separation and can play safely with the sensors. these are often near the life (electric cabinet/enclosures) on the other side (sensors /field) i use the MAX485 or an SN75HVD12DR RS485.
      Second question: is it possible to send a message from one sensors to another on the same bus? Without the need to use code in the GW? to route the recaiver?
      Regards,
      Stefan.

      posted in General Discussion
      stedew
      stedew
    • RE: Alternative to ArduinoIDE

      @Daniel-Oliveira
      Hello Daniel for what it's worth: Jantje posted a Fix in Github:
      the selection of subfolders included to the path is not consistent with the Arduino IDE

      Just have to test it further
      Regards,
      Stefan

      posted in General Discussion
      stedew
      stedew
    • RE: Best IDE to use for MySensors projects

      @ivankravets

      Ok as i mentioned before:
      At start nothing worked like i wanted in PIO then start reading....
      Testing &implement all steps that seems to be needed (forums are top sometimes 🙂
      Then changed computer (Wife...) and re-install everything from scratch.
      And so i came to this exhaustive (wrong) list
      So now the corrected one:

      PlatformIO:
      1) Choose Board (here tested with UNO)
      2) Choose Dir (only existing dir no create possible) (First make MKDIR BatteryPoweredSensor )
      2) Choose Dir ( existing dir or create "BatteryPoweredSensor" )
      3) Copy code file from Mysensors example dir to PlatformIO \src dir (right click open in explorer)
      4) Enable Use development Version of PlatformIO (at the moment for PIO 3.0) in settings
      ~~ 5) Add PATH string variable in settings (Good explanation anyway)~~
      ~~6) Start cmd (Powershell in Windoze) from PlatformIO ~~
      7) Execute the cmd >> platformio lib install 548 (For Mysensors 2.0 lib)
      5 ) add 1 line to your platformio.ini config: lib_deps = MySensors (Dmnn that i try-ed already did not work then ?? to many modifs made i think)
      6 ) Compile info: on my Laptop (slow one) compiles MySerialGw in 2sec!! (record for PIO)
      7 ) Download to controller

      About the other topics:
      Refractoring is handy especialy when you use constants over severall files.
      I am a chaotic person so i tend to forget one enum somewhere...
      Goto declaration >> ok have to switch OS maybe not you/team to blame.
      -Local history will try /need it (same problem as refractor point 😞 )
      -upload_port very good one... will test it .

      --Improvements ?? Don't know i already own you a couple of beers i think.
      I believe it is maybe handy to have a write up with screenshots "Adventures migration from Arduino to PIO".

      Regards,Stefan.

      posted in Development
      stedew
      stedew
    • RE: Best IDE to use for MySensors projects

      @ivankravets
      Hello Mr Ivankravets

      Ok birthday is done and bottles empty....
      -Well When you compare to Arduino IDE vs PlatforIO is something slightly different:
      Running the "BatteryPoweredSensor.ino" (Mysensors 2.0) example in Arduino 1.6
      1)Load new Sketch "Examples">>Mysensors >> BatteryPoweredSensor
      2)Compile >>will not work for all boards (due to INTERNAL is not defined for all AVR members )
      3)Download to controller

      PlatformIO:
      1) Choose Board (here tested with UNO)
      2) Choose Dir (only existing dir no create possible) (First make MKDIR BatteryPoweredSensor )
      3) Copy code file from Mysensors example dir to PlatformIO \src dir (right click open in explorer)
      4) Enable Use development Version of PlatformIO (at the moment for PIO 3.0) in settings
      5) Add PATH string variable in settings (Good explanation anyway)
      6) Start cmd (Powershell in Windoze) from PlatformIO
      7) Execute the cmd  >>  platformio lib install 548 (For Mysensors 2.0 lib)
      8) Compile
      9) Download to controller
      

      -This being sayed for these additional steps you get something what is non existing in Arduino ide:
      +AutoComplete variables /suggest with function prototypes
      +Acces to all used code off the included library
      +Compile in seconds

      -Still some questions also:
      Is there a quick way to refractor over source files (not readed the manual)?
      Goto declaration does not work (maybe my fault) Clang is installed however.
      Local version control?
      Specify wich serial port for upload (and not use the default first one)

      Tnx in advance,
      Stefan.

      posted in Development
      stedew
      stedew
    • RE: Best IDE to use for MySensors projects

      Hmm tnx for the clarification
      I have a small party here (Wife birthday) so I will try to reproduce it later.
      Otherwise the automatic script Divorse now will start...
      regards,
      Stefan.

      posted in Development
      stedew
      stedew
    • RE: Best IDE to use for MySensors projects

      Hello Mr Kravets,
      Can you give a hint/short explanation why Mysensors 2.0 Compiles ok in the upgraded version (the development branch). I can understand its maybe one off your internal secrets but i think that it can be benificial for others. I love a lot one off the "concurrent" IDE (Arduino Eclipse) and the (for my case) Problem is that it doesn't compile Mysensors 2.0. I assume with my limited knowledge and observations off the compiler errors the problems there are related..
      -I Also tested the build and it took severall attempt to get it compiling. Unfotunatly i cannot reproduce it (Windows usr 😉 ) I had to fiddle severall times in the PATH var and settings and restart the IDE ....

      Anyway I hope that Arduino ide sees one day the Light and gets some inspiration on a project like this or even better start co-operating....
      Good work !!!

      posted in Development
      stedew
      stedew
    • RE: Blindcontroller with PB local control

      Again right.. but the class definition is in the BL_Control.h file (line 47) The reason not to put the logic is that i yust want some sceleton for this kind of physical controller now i don' t have to include write and reads in the class and i can re-use it maybe for a PB dimmer. That off the declaration with the pinmodes is a habbit from the plain C period and assembler adventures with the AVR. There i set my outputs to a safe state before setting the DDR(x) register. As far as i assume the DDR is only relevant when you read the input (or want to do a logic operation on the input/output state. And it is overkill to write this in C++. But for me i consider it as a good excercise. And no i don't have a question I only wanted it to publish so others can steal maybe a idea Cheers,

      posted in My Project
      stedew
      stedew
    • RE: Blindcontroller with PB local control

      @TheoL

      Hello TheoL i think you are right, but it is hard to copy/past a project to a forum. But why not i changed the post and now almost everybody can see how crapy code i write 😃
      Regards,
      Stefan.

      posted in My Project
      stedew
      stedew
    • RE: Blindcontroller with PB local control

      This is part 2:

      Under is the controller object it was (and is) for me an excercice how to make a modular c++ program
      Al hw dependency is left out (except millis & Serial.print) everything should behave like defined on a different platform.
      There is plenty room to improve this so shoot: be critic but fair wat i can improve (and how)

      File: "Bl_Control.cpp"

      
      /*
       * Bl_Control.cpp
       *
       *  Created on: 20 jul. 2016
       *      Author: Stefan
       *
       *
       *      Setpoint controller up/down
       * 		Allows you to monitor and control a setpoint vs PV
       * 		1 	- use a local inputs byte to increase or decrease the position
       * 		2 	- send a setpoint/position request by a host
       * 		3	- Set a Factor (gain) to change the ratio PV /SP
       *
       *
       *	Version history:
       *	0.1	:	build object class
       *	0.2	: 	Added a factor (gain) to allow a wider use  and removed "magic numbers" in code
       *	0.3	:	Fix for nasty RT-bug when gain gets higher then 131 >>integer overflow when multiply with BL_MAX_TIME_UP (250)
       *
       *
       *	TODO:
       *		:optimization use off variables
       *		:implemnt auto teach sequence
       */
      
      #if defined(ARDUINO) && ARDUINO >= 100
      #include "Arduino.h"
      #else
      #include "WProgram.h"
      #endif
      
      #include "Bl_Control.h"
      
      
      Bl_Control::Bl_Control(){
      
      		_previoustMillis_inp_scan= millis();//init the scan clock when object is created
      		_SP =BL_SP_MIN; 			//Current active SP
      		_Remote_SP =BL_SP_MIN; 	//Last received SP received from the Host
      		_Remote_CMD = t_BL_Cmd::BL_CMD_NONE;//Last received Command from the Host
      		_Local_CMD =  t_BL_Cmd::BL_CMD_NONE; ;	//Last received Command from the inputs
      		_Runtime = 0;				//Time Controller is running
      
      		_Error =0;					//Module in error
      		_PV =0; 					//Global internall Process_Value (PV) aka the actual (or estimated) position off the blind
      		_ErrRunTmr =0;
      		_Error=0;
      		_tmrLocalCmddwn =t_BL_Cmd::BL_CMD_NONE;
      		_tmrLocalCmdup =t_BL_Cmd::BL_CMD_NONE;
      		_prev_rem_cmd= t_BL_Cmd::BL_CMD_NONE;
      		_inputs=0;
      		_ouputs=0;
      		_RunCtrlCmd = t_BL_Cmd::BL_CMD_NONE;
      		_RunCtrlprevLocCmd = t_BL_Cmd::BL_CMD_NONE;
      		_Gain_PV =100;			//Sets the controller to center gain (1/1)= 100%
      
      
      
      }
      
      /**
       * Get_Gain_PV	:	Returns the ratio (in %) _PV to _SP
       * inputs are 	:	None
       * Chances  	:	None
       * Returns 		: 	Factor (min)
       */
      uint16_t Bl_Control::Get_Gain_PV(){
      	return _Gain_PV;
      }
      
      /**
       * Set_Gain_PV	:	Set the ratio _PV to _SP
       * inputs are 	:	Newgain 10(%) min to 1000% max
       * Chances  	:	_Gain_PV
       * Returns 		: 	None
       */
      void Bl_Control::Set_Gain_PV (uint16_t NewGain){
      
      	if(_Gain_PV!=NewGain){
      #if BL_DEBUG -1
      		Serial.print("N_Max_PV ");
      		Serial.println(NewGain);
      #endif
      	//We avoid float by multiply the result by 10
      	// 	10 is 10%
      	//	1000 is 1000%
       //TODO: Remove test //(Domoticz gives 1 to 100 and not 10 to 1000
      		NewGain = NewGain *10;
      
      		if (NewGain >BL_PV_MAX ) {//Limit is 1000%
      			NewGain = BL_PV_MAX  ;
      		}else if (NewGain > BL_PV_MIN  ){
      			NewGain=(NewGain );
      		}else{
      			NewGain = (BL_PV_MIN ) ;//Limit is 10
      		}
      		_Gain_PV=NewGain;
      
      #if BL_DEBUG -1
      		Serial.print("New_Gain: ");
      		Serial.println(_Gain_PV,DEC );
      #endif
      	}
      
      }
      
      /**
       * bl_Process	 Main worker when called the period elapsed is evaluated if expired the internal routines
       * 				 shall be executed
       * inputs are 	:	None
       *
       * Chances  	:	_previoustMillis_inp_scan (Time keeper)
       * 				:
       * Returns 		: 	None
       */
      void Bl_Control::bl_Process (){
      
      	unsigned long currentMillis = millis();
      	if (currentMillis - _previoustMillis_inp_scan >= UPDATE_INPUTS_ms) {
      
      		Update_Local_cmd();
      		Run_ctrl( );
      		_previoustMillis_inp_scan = currentMillis;
      	}
      
      
      }
      
      
      /**
       * Update_Local_cmd	 - Evaluate the local input byte and update the _Local_CMD off the blind
       * inputs are 	:	none
       * 				:	(except the internal _inputs)
       * outputs are 	:	none
       * 				:
       * Returns 		: 	_Local_CMD
       *
       * routine is called on a regular (timed)interval and manipulates _Local_CMD
       * The routine sets the cmd_state and stores the last command executed
       * 1° a Short (input)cmd_up/cmd_dwn gives a run to the direction requested (MAX/MIN)
       * 2° Long cmd_up/cmd_down gives a run state UP/DWN until release (tipping)
       * 3° cmd_up && cmd_dwn at same time : >> reset Error state
       * 4° A retrigger (when running to the max/min) >> stop is executed
       *
       */
      uint8_t Bl_Control::Update_Local_cmd (void)
      {
      	uint8_t tmp_cmd = _Local_CMD;
      //First test if there is a error reset request (both cmd_up && cmd_dwn active)
      	if (((bitRead(_inputs, t_BL_InBits::INCR ) != 0 )&& (bitRead(_inputs, t_BL_InBits::DECR) !=0))) {
      		_tmrLocalCmddwn =0;//Reset counters /Timers
      		_tmrLocalCmdup = 0;
      		_Local_CMD = t_BL_Cmd::BL_CMD_RST;//Store the last action
      		_Error = false;//
      		return _Local_CMD;
      
      	}
      	if (_Error) {
      		return _Local_CMD;
      	}
      
      	// Blind up evaluation
      	if (bitRead(_inputs,t_BL_InBits::INCR)) {
      		if (_tmrLocalCmdup <= BL_T_Hold) { 			//Increase hold counter
      			_tmrLocalCmdup++;
      			tmp_cmd = t_BL_Cmd::BL_CMD_INC;				//Sets a increase marker (tipping mode)
      			if ( _Local_CMD == t_BL_Cmd::BL_CMD_UP)  {	//Repeated impulse command change to tipping mode
      				_tmrLocalCmdup = BL_T_Hold;			//set timer to holdlimit so we can stop at PB release
      			}
      		}else{
      		}
      
      	} else {
      		if ((_tmrLocalCmdup !=0) && (_tmrLocalCmdup < BL_T_Hold)){
      		// cmd_up is impulsed
      			tmp_cmd = t_BL_Cmd::BL_CMD_UP;
      		}else{
      			// button was hold longer then T_Hold (Tipping) but now released
      			if (_tmrLocalCmdup >=BL_T_Hold) tmp_cmd = t_BL_Cmd::BL_CMD_STOP;
      		}
      		// When button is released reset the counter
      		_tmrLocalCmdup =0;
      	}
      
      	// Blind Down evaluation
      	if (bitRead(_inputs, t_BL_InBits::DECR )) {
      		//st_tmrhld_Localup=0;	// When we go down up is reset
      		if (_tmrLocalCmddwn <= BL_T_Hold){
      			_tmrLocalCmddwn++; //Increase hold
      			tmp_cmd = t_BL_Cmd::BL_CMD_DEC;
      			if ( _Local_CMD == t_BL_Cmd::BL_CMD_DWN)  {//Repeated impulse command change to tipping mode
      				_tmrLocalCmddwn = BL_T_Hold;			//set timer to holdlimit so we can stop at PB release
      			}
      		}
      	} else {
      		if ((_tmrLocalCmddwn !=0) && (_tmrLocalCmddwn < BL_T_Hold)){
      		// cmd_dwn is impulsed
      			tmp_cmd = t_BL_Cmd::BL_CMD_DWN;
      		}else{
      		// button was hold longer then T_Hold (tipping) but now released >>release Tip
      			if (_tmrLocalCmddwn >=BL_T_Hold) tmp_cmd = t_BL_Cmd::BL_CMD_STOP;
      		}
      		// When button is released reset the counter
      		_tmrLocalCmddwn =0;
      
      	}
      
      	if (tmp_cmd != _Local_CMD)
      	{
      		_Local_CMD = tmp_cmd;
      	}
      
      	return _Local_CMD;
      }
      
      /**
       * bl_GetOutputs	Returns the current output bits to the caller
       * inputs are 	:	None
       *
       * Chances  	:	None
       * 				:
       * Returns 		: 	Output bits
       */
      uint8_t Bl_Control::bl_GetOutputs (void)
      {
      	return _ouputs;
      }
      
      /**
       * UpdateRemote_cmd	 - Evaluate the messages from the host (here domoticsz)
       * inputs are 	:	MyMessage
       *
       * Chances  	:	_Remote_SP,
       * 				:
       * Returns 		: 	remote_Commandstate
       *
       * routine is called when a message from the host is received
       * The routine sets the cmd_stat and stores the last command if changed
       * The routine interprets the message and send a open/close or run to new setpoint
       */
      
      uint8_t Bl_Control::UpdateRemote_cmd (uint8_t Sp, uint8_t cmd_Type )
      {
      	uint8_t tmp_cmd=  _Remote_CMD;//Current command
      	uint8_t tmp_SP ;// Current Setpoint
      
      	tmp_SP = _Remote_SP;//Store the current SP
      
      
      	if (bitRead(cmd_Type ,0)) { // This is a SP change request
      
      		 if (_Remote_SP != Sp) {//Is SP from host different to current one?
      #if BL_DEBUG -1
      				Serial.println("BL_RM");
      				Serial.print("New SP: ");
      				Serial.println(val);
      #endif
      
      			tmp_SP = Sp; 		//set SP to the requested value
      			tmp_cmd = BL_CMD_RUN;
      		 }else {//Nothing to do except change local static
      			 tmp_cmd = BL_CMD_NONE;//reception off same as previous SP
      		}
      	}
      	else if (bitRead(cmd_Type ,1)|| bitRead(cmd_Type ,2)) {//Position request (full open / full closed)
      
      			if (bitRead(cmd_Type ,1)) { //I Use a inverted blind on the GUI
      				if (_Remote_CMD ==BL_CMD_DWN ) {//Re-fire in Run will trigger a stop
      					tmp_cmd = BL_CMD_STOP;//Second push to full position >> stop
      #if BL_DEBUG -1
      					Serial.println("BL STP");
      #endif
      				}else{
      					tmp_SP = BL_SP_MIN ;//adjust SP to min (close)
      					tmp_cmd= BL_CMD_DWN;
      #if BL_DEBUG -1
      					Serial.println("BL_DWN");
      #endif
      				}
      			} else {
      				if (_Remote_CMD ==BL_CMD_UP) {
      					tmp_cmd = BL_CMD_STOP;//Second push to full position >> stop
      #if BL_DEBUG -1
      					Serial.println("BL STP");
      #endif
      				} else {
      					tmp_SP = BL_SP_MAX ;//adjust SP to max
      					tmp_cmd= BL_CMD_UP;
      #if BL_DEBUG -1
      					Serial.println("BL_UP");
      #endif
      				}
      			}
      	 }
      	if (_Remote_CMD == tmp_cmd){
      		if (_Remote_SP != tmp_SP) {
      			_Remote_SP = tmp_SP;				//Overwrite back (modified) SP to caller
      			_Remote_CMD = BL_CMD_RUN;			//Set Run State to start
      			return _Remote_CMD;
      		} else {
      			return BL_CMD_NONE;					//Nothing changed
      		}
      	}else{
      		_Remote_SP = tmp_SP;					//write back (modified) SP to caller
      		_Remote_CMD = tmp_cmd;
      		return _Remote_CMD;
      	}
      
      }
      
      /**
       * SetInputs	:	changes the local inputbits (input command word)
       * inputs are 	:	inc
       * 				:	dec
       * 				:	RunCurrent
       *
       * outputs are 	:	none (manipulates the internal input byte)
       * Returns 		: 	none
       *
       * call this routine to reflect input changes to the ( internal )input controller
       */
      void Bl_Control::bl_SetInputs(uint8_t inc , uint8_t dec, uint8_t RunCurrent  ){
      	if (inc) 	bitSet(_inputs,t_BL_InBits::INCR);	else		bitClear(_inputs,t_BL_InBits::INCR);
      	if (dec)	bitSet(_inputs,t_BL_InBits::DECR);  else	bitClear(_inputs,t_BL_InBits::DECR);
      	if (RunCurrent) 	bitSet(_inputs,t_BL_InBits::CURSNS);	else		bitClear(_inputs,t_BL_InBits::CURSNS);
      }
      /**
       * bl_RunErrorLed	:Give some feedback for the user
       * inputs are 	:	inc
       * 				:	dec
       * 				:	RunCurrent
       *
       * outputs are 	:	none
       * 				:
       * Returns 		: 	State for the error/run Led
       *
       * call this routine for getting the led state (In Run slow blink / In error fast blink)
       *
       */
      uint8_t Bl_Control::bl_RunErrorLed(void){
      
      
      
      	if (_Error){
      
      		if (bitRead(_ErrRunTmr,1)){
      			return true;
      		}else{
      			return false;
      		}
      	}else{
      
      		if ((bitRead(_ouputs,t_BL_OutBits::BL_RN_UP))||bitRead(_ouputs,t_BL_OutBits::BL_RN_DWN)  ) {
      			if (bitRead(_Runtime,2)){
      				return true;
      			}else{
      				return false;
      			}
      			return true;
      		}else {
      			if (_ErrRunTmr) _ErrRunTmr=0;
      			return false;
      		}
      	}
      }
      /**
       * Run_ctrl	 	- main worker controls the movement off the blind
       * inputs are 	: _Error, _SP, _PV (internal)
       * 				:
       * outputs are 	: none
       * 				:
       * Returns 		: 	_ouputs (for I/0)
       *
       * routine is called on a regular (timed)interval and is controlled by the inputs  byte(s)
       * Commands are stored and executed if a change occurs compared to previous (call)
       * Also an error will cause a stop immediately
       * Total runtime is controlled and generates a error if exceeded >> in Error no remote commands are accepted only the local reset cmd
       *
       */
      uint8_t Bl_Control::Run_ctrl (void){
      
      	uint32_t tmp_l1 = 0;//Local scratch var
      
      //First Test for a pending error
      	if (_Error  ) {
      		_RunCtrlCmd=BL_RN_ERR;
      		_Runtime =0;//Stop internal timer
      		if (_ErrRunTmr == 0xff) {
      			_ErrRunTmr = 1;
      		} else {
      			_ErrRunTmr++;
      		}
      
      		return _RunCtrlCmd;//Exit here no need to continue
      	}else{
      		_ErrRunTmr=0;
      
      	}
      //TODO: interlocking the remote /local should be optimized
      //No errors: evaluate witch command must be executed check for (new) local/remote command
      	if (_Local_CMD !=_RunCtrlprevLocCmd ) {
      		//Local command different from current run state store in _RunCtrlCmd
      		_RunCtrlCmd = _Local_CMD; //Make the new stat the active one
      #if BL_DEBUG-1
      		Serial.print("BL_LC");
      		Serial.println(_RunCtrlCmd);
      #endif
      	}
      		else if (_Remote_CMD != _prev_rem_cmd) {
      #if BL_DEBUG-1
      			Serial.println("BL_RM");
      #endif
      			_RunCtrlCmd =_Remote_CMD;//copy the remote cmd to local
      	}else{
      		//Leave it there is no new cmd
      	}
      
      //Setpoint manipulator/Controller (depends on (new)input command
      	switch (_RunCtrlCmd) {
      	case BL_CMD_STOP:
      		_SP = _PV;//Assign the actual PV to the internal SP
      		break;
      	case BL_CMD_INC ://increase Setpoint
      		 //only increase if SP is smaller then max PV
      			if (_SP < (_Gain_PV)){
      				_SP++ ;
      				if (_Runtime ==0) _Runtime =1;
      			}
      
      		break;
      	case BL_CMD_UP://Setpoint to max
      		if (_SP != _Gain_PV) {
      			_SP = _Gain_PV ;
      			if (_Runtime ==0) _Runtime =1;			//Run ...Run
      		}
      		break;
      	case BL_CMD_DEC ://Setpoint decrease (tipping)
      		if (_SP != BL_SP_MIN){
      			if(_SP > (BL_SP_MIN) ){
      				_SP-- ;
      				if (_Runtime ==0) _Runtime =1;
      			}
      #if BL_DEBUG-1
      
      		Serial.print("DSP: ");
      		Serial.println(_SP,DEC );
      #endif
      		}
      		break;
      	case BL_CMD_DWN ://Setpoint to min
      		if (_SP != BL_SP_MIN) {
      			_SP = BL_SP_MIN;
      			if (_Runtime ==0) _Runtime =1;
      		}
      
      		break;
      	case BL_CMD_RUN :								//Setpoint received from host
      
      		tmp_l1 =(_Remote_SP * _Gain_PV /BL_SP_MAX);	//First calculate the scaled setpoint from the host
      		if (_SP != tmp_l1){							//is this a different setpoint ?
      
      			_SP = tmp_l1;
      #if BL_DEBUG-1
      				Serial.print("Sp: ");
      				Serial.println(_SP,DEC);
      				Serial.print("_PV: ");
      				Serial.println(_PV,DEC );
      #endif
      			if (_Runtime ==0) _Runtime =1;
      		}
      		break;
      	default:
      		break;
      	}
      
      
      //Position (PV) Generator  there is no feedback position so it is simulated by counters/timers
      	if (_SP ==( _PV)   ){
      		bitClear(_ouputs,  t_BL_OutBits::BL_RN_DWN);
      		bitClear(_ouputs,  t_BL_OutBits::BL_RN_UP);
      		_Runtime =0;//Stop
      	}else{
      
      		if ((_SP ) > (_PV) ){
      			bitClear(_ouputs,  t_BL_OutBits::BL_RN_DWN);
      			bitSet(_ouputs,  t_BL_OutBits::BL_RN_UP);
      			if ((_PV < _Gain_PV) && (_Runtime !=0))_PV++;
      
      		}else{
      			//(_SP < _PV)
      			bitClear(_ouputs,  t_BL_OutBits::BL_RN_UP);
      			bitSet(_ouputs,  t_BL_OutBits::BL_RN_DWN);
      			if (_PV>=BL_SP_MIN) _PV--;
      		}
      	}
      	// Feedback that there is still current flowing
      	if (bitRead(_inputs,t_BL_InBits::CURSNS )){
      		// We still are driving the outputs increase run time
      		if (_Runtime){
      			// FIX 0.3	: the line beneath uses a cast (uint32_t) on a constants omitting this will give you a few hours joy...
      			tmp_l1 =(uint32_t)BL_MAX_TIME_UP * _Gain_PV / (uint32_t)BL_SP_MAX ;	//First calculate the max (scaled) Run time
      #if BL_DEBUG -1
      			if (_Runtime ==2) {
      				Serial.print("Max_PV: ");
      				Serial.println(tmp_l1,DEC);
      			}
      #endif
      			if  ( _Runtime < tmp_l1)_Runtime ++;				//If not overtime increase timer
      #if BL_DEBUG -1
      				Serial.print("RT: ");
      				Serial.println(_Runtime,DEC);
      				Serial.print("PV: ");
      				Serial.println(_PV,DEC);
      #endif
      		}
      
      	}else{
      		//Current is dropped >> Motor off or (in this case) end limit reached
      		if ((  bitRead(_ouputs, t_BL_OutBits::BL_RN_UP ) ||bitRead(_ouputs, t_BL_OutBits::BL_RN_DWN )) && (_Runtime>WAITFORCURRENT) )
      		{
      //Todo: when testing this with feedback maybe this can be optimized to _PV = _SP; (as this will probably be true )
      			//When the current is gone we have reached a end limit
      			if (  bitRead(_ouputs, t_BL_OutBits::BL_RN_UP )){
      					bitClear(_ouputs,  t_BL_OutBits::BL_RN_UP);
      					_PV = _Gain_PV;//Reached the Max limit ...inform the host
      			}
      			if (  bitRead(_ouputs, t_BL_OutBits::BL_RN_DWN )){
      				bitClear(_ouputs,  t_BL_OutBits::BL_RN_DWN);
      				_PV = BL_SP_MIN;//Reached the min limit ...inform the host
      			}
      			//The current is gone but still driving UP/DOWN stop it (should be redundant here)
      			bitClear(_ouputs,  t_BL_OutBits::BL_RN_DWN);
      			bitClear(_ouputs,  t_BL_OutBits::BL_RN_UP);
      		}
      	}
      
      	// Guard the max run time (Up/down time)
      	if (_Runtime){
      		// FIX 0.3	: the line beneath uses a cast (uint32_t) on a constants omitting this will give you a few hours joy...
      		tmp_l1  = (uint32_t) BL_MAX_TIME_UP *_Gain_PV / (uint32_t)BL_SP_MAX;//First calculate the max (scaled) Run time
      
      		if ( _Runtime >= tmp_l1) {
      			bitClear(_ouputs,  t_BL_OutBits::BL_RN_DWN);	//Overrun (blokking?) >> stop
      			bitClear(_ouputs,  t_BL_OutBits::BL_RN_UP);
      			bitSet(_ouputs,  t_BL_OutBits::BL_RN_ERR);
      			_Error = true;
      #if BL_DEBUG-1
      			Serial.print("RT: ");
      			Serial.print(_Runtime);
      			Serial.print(" HL: ");
      			Serial.print(tmp_l1,DEC);
      			Serial.print(" G: ");
      			Serial.print(_Gain_PV);
      
      			Serial.println(" TIME_OUT ");
      #endif
      		}
      	}
      
      	if (_Local_CMD !=_RunCtrlprevLocCmd ) {					//Update the command switcher for next entry
      		_RunCtrlprevLocCmd = _Local_CMD;
      	}else if  (_Remote_CMD !=_prev_rem_cmd ){
      		_prev_rem_cmd = _Remote_CMD;
      	}
      	return _ouputs;// return  the Run_Result
      }
      /**
       * Get_PV	 	:	Returns the current ProcessValue (actual state) or feedback in %
       * inputs are 	: 	None
       * Changes		: 	None
       * 				:
       * Returns 		: 	_PV
       *
       */
      uint8_t Bl_Control::Get_PV (void){
      	return ((_PV*BL_SP_MAX)/_Gain_PV);
      }
      

      At last the header File "Bl_Control.h"

      // - function definitions (prototypes)
      // - include files
      // - extern variable definitions
      // In the appropriate section
      
      #ifndef _BL_Control_H_
      #define _BL_Control_H_
      #include "Arduino.h"
      //add your includes for the project BlindController here
      #include <inttypes.h>
      
      //end of add your includes here
      
      
      
      //add your function definitions for the project BlindController here
      
      #define BL_DEBUG 1			//Enable/disable debugging msg (to serial)
      
      #define UPDATE_INPUTS_ms 50UL	// scan time inputs for change
      
      #define WAITFORCURRENT 3 	//Allow the current to come up when outputs activate
      
      #define BL_T_Hold 5			// This is the number off scans before a button is considered as hold (Tipping)
      #define BL_SP_MIN 0x00		// SP_LL no comment....
      #define BL_SP_MAX 100		// SP_H This value is the value considered as 100% output
      
      
      #define BL_MAX_TIME_UP 250 	//With a scan time off 50mSec the this give only 12Sec (1000mSec/50 * t_Scan_SeC < 0xFF)
      							//on the other hand there is also a factor (
      
      #define BL_PV_MIN 10		// Min gain percentage (10%)
      #define BL_PV_MAX 1000UL	// Min gain percentage (1000%)
      
      
      
      #if BL_MAX_TIME_UP <= BL_SP_MAX //When changing parameters test if the SP is reachable without error
      	#error "Attention !! you can't reach the max allowed SP val in one run with this setting!"
      #endif
      
      typedef enum BL_OutBits  { BL_RN_UP, BL_RN_DWN, BL_RN_ERR}t_BL_OutBits;
      typedef enum BL_Cmd {BL_CMD_NONE, BL_CMD_STOP,BL_CMD_INC, BL_CMD_UP, BL_CMD_DEC ,BL_CMD_DWN,BL_CMD_RST ,BL_CMD_RUN} t_BL_Cmd ;
      
      typedef enum  BL_InBits{ INCR, DECR, CURSNS}t_BL_InBits;
      
      class Bl_Control
      {
      
      public:
      	// Create an instance of the BlindController 
      	Bl_Control(); 
      	// call this to run the timers
      	void bl_Process (void);
      	
      	//Get the outputbits
      	uint8_t bl_GetOutputs (void);
      	//Update info from the host (updates the remote cmd bits)
      	uint8_t UpdateRemote_cmd (uint8_t Sp, uint8_t cmd_Type );
      	//Set the inputs 
      	void bl_SetInputs (uint8_t inc , uint8_t dec, uint8_t RunCurrent  );
      	uint8_t bl_RunErrorLed (void);
      	uint8_t Get_PV (void);
      	uint16_t Get_Gain_PV ();
      	void Set_Gain_PV (uint16_t fakt);
      
      	
      
      private:
      	//SP and PV updater
      	uint8_t Run_ctrl (void);
      	// evaluate the inputcmd (timers)
      	uint8_t Update_Local_cmd (void);
        
      
      
        
        	
      protected:
      	 uint8_t 	_tmrLocalCmdup;				//Timer off the PB UP
      	 uint8_t  	_tmrLocalCmddwn;			//Timer off the PB DWN
      	 uint8_t 	_ErrRunTmr;					//Timer off the error/Run
      
      	 uint8_t 	_RunCtrlCmd;				//the active command off Controller
      	 uint8_t 	_RunCtrlprevLocCmd ;		//Store the previous local state
      
      	 uint8_t 	_prev_rem_cmd;				//Store the previous state at end off routine
      	 uint8_t 	_inputs;					//InputBits
      	 uint8_t  	_ouputs;					//OutputBits
      	 
      	 //timer logic to schedule updates ,cmd ,inputs,...
      	 unsigned long _previoustMillis_inp_scan ;
      	
      	uint8_t _Remote_SP; 					//Last received SP received from the Host
      	uint8_t _Remote_CMD ;					//Last received Command from the Host
      	uint8_t _Local_CMD ;					//Last received Command from the inputs
      	uint16_t _Runtime ;						//Time Controller is running
      	
      	uint16_t _SP ; 							//internal Setpoint
      	uint16_t _PV; 							//Global Process_Value (PV) aka the actual (or estimated) position
      		
      	uint8_t _Error;							//Module in error
      	uint16_t _Gain_PV ;						//Factor for _PV to reach the setpoint (in %)
      	
      };
      
      
      //Do not add code below this line
      #endif /* _BL_Control_H_ */
      
      
      posted in My Project
      stedew
      stedew
    • Blindcontroller with PB local control

      Hello,
      This sketch can be used for control a blind (local + remote) it is working but there is still room for improvement ... to say the least
      Any suggestions remarks are welcome
      heu it is not tested in arduino dev (now it is 2016/08/03) (i use eclipse arduino IDE)

      Update 2016/08/03:
      insert files as requested by TheoL (and removed the ZIP file
      **ATTENTION ** i could not make it in one post so you need also part 2 !!

      This is the main sketch (and corrected smal bug)

      "Rfm69_BlindController.ino"

      // Do not remove the include below
      #include "Rfm69_BlindController.h"
      #include "Bl_Control.h"
      
      
       /*
        BlindController for MySensors (or any other local/remote control )
      
        This is a adaption off this sketch (garage door control)
        original is @ https://forum.mysensors.org/topic/4059/automated-garage-door/21
        from user https://forum.mysensors.org/user/dbemowsk
        However not much is still in it
      
      
        July 20,2016
      
        This will allow the MySensors gateway to monitor and control your blinds.  This sketch monitors the actual position
        of the blind(s). It CAN use a sens input to detect current flowing (true/false)
        when the blind is running and current stops (current gets zero) we know the demanded position limit is reached,
        in the required direction (hard limit up/down).
      
        This sketch features the following:
      
        Allows you to monitor and control the blind position and return it's status based on the following:
      
          1   - use two local inputs (buttons) to increase or decrease the position
      
          2   - sending a setpoint/position request by a host (Mysensor here)
      
        3 - Send a Factor (gain) to fine tune the time run up/down)
      
        PARTS LIST:(for 2 blinds)
        Moteino
      
        4 3 or 5v relay
        4 2N3904 transistor for relay
        4 1k resistor
        2 2k7 Resistor (for Led)
        2 Led (error /run)
      
      HW CONFIG;  (here moteino)
        Relay UP      D5  (Blind1)
        Relay Down      D6  (Blind1)
        Error/Run Led     D7  (Blind1)
      
        InputUP       D14 (Blind1)
        InputDown       D15 (Blind1)
        Currentsense    D16 (Blind1)
      
        Relay UP      D3  (Blind2)
        Relay Down      D4  (Blind2)
        Error/Run Led     D17 (Blind2)
      
        InputUP       D18 (Blind2)
        InputDown     D19 (Blind2)
        Currentsense    A6  (Blind2)
      
        Version history:
        0.1 : Refractor original source (garage opener see ref)
        0.2 :   Build original concept without object
        0.3 :   Rebuil d with object class
        0.4 :   Added a factor (gain) to allow a wider use  and removed "magic numbers" in code
        0.5 : Added code for retrieving factor from EEPROM
              : added fix for nasty RT-bug when gain gets higher then 131 (integer overflow)
      */
      
      #include <MyTransportRFM69.h>
      #include <MyHwATMega328.h>
      #include <MySensor.h>
      //#include <SPI.h>
      
      
      
      #define SKETCH_NAME "BlindController"
      #define SKETCH_VERSION "0.4"
      
      
      #define NODE_ID         85  //Define The node <> 0 (i don't want a auto assignment see setup @mySensors)
      
      #define CHILD_ID_SP_BL1     52  //Here we receive the setpoint
      #define CHILD_ID_GAIN_BL1     53  //This is the gain (value from 10 to 1000%!)
      
      
      #define CHILD_ID_SP_BL2     55  //Here we receive the setpoint
      #define CHILD_ID_GAIN_BL2     56  //This is the gain (value from 10 to 1000%!)
      
      #define EPROM_GAIN_BL1      1 //This is the location where the factor is stored  (Blind1)
                        //After a power failure this value will be restored
      #define EPROM_GAIN_BL2      3 //This is the location where the factor is stored (Blind2)
      
      
      
      #define DI_BL1_UP         14  //Pin used for command up
      #define DI_BL1_DWN        15  //Pin used for command Down
      #define AI_BL1_SENS       16  //Pin used Sensing the current (Yes/no)
      
      #define DO_BL1_MOTOR_UP     5 //Pin activate relay up
      #define DO_BL1_MOTOR_DWN    6 //Pin activate Relay Down
      #define DO_BL1_ERR_RUN      7 //Pin activate Run/error
      
      
      #define DI_BL2_UP         18  //Pin used for command up
      #define DI_BL2_DWN        19  //Pin used for command Down
      #define AI_BL2_SENS       A6  //Pin used Sensing the current (Yes/no)
      
      #define DO_BL2_MOTOR_UP     3 //Pin activate relay up
      #define DO_BL2_MOTOR_DWN    4 //Pin activate Relay Down
      #define DO_BL2_ERR_RUN      17  //Pin activate Run/error
      
      
      
      
      #define MOTOR_ON        0 // GPIO value to write to turn on attached relay
      #define MOTOR_OFF         1   // GPIO value to write to turn off attached relay
      
      
      #define DEBUG_BLINDCONTROLLER   0 // Set to non zero for debugging
      
      // new V_TEXT variable type (development 20150905)
      //const int V_TEXT = 47 ;
      // new S_INFO sensor type (development 20150905)
      //const int S_INFO = 36 ;
      
      
      //Some timer logic to do updates on the inputs
      unsigned long bl_previoustMillis_inp_scan =0;
      
      
      
      MyMessage msg(CHILD_ID_SP_BL1, V_PERCENTAGE);// global response object
      
      MyTransportRFM69 transport;       //Attention most users will use a NRF here!!
      // Hardware profile
      MyHwATMega328 hw;
      
      MySensor gw(transport,hw);
      
      //MyMessage msgStatus(CHILD_ID_STATUS, V_TEXT);
      
      Bl_Control blind1,blind2;     //Handle to controller Instance
      
      /**
       * Function Prototypes
       */
      // hmm.. seems not needed in Arduino
      
      /**
       * setup - Initialize the HW
       */
      void setup() {
      
      //BLIND1
        //initialize the inputs Blind1
        pinMode(DI_BL1_UP, INPUT_PULLUP);
        pinMode(DI_BL1_DWN, INPUT_PULLUP);
        pinMode(AI_BL1_SENS,INPUT_PULLUP);
        //Set outputs to safe state and init
        digitalWrite( DO_BL1_MOTOR_UP,MOTOR_OFF);
        digitalWrite( DO_BL1_MOTOR_DWN,MOTOR_OFF);
        digitalWrite(DO_BL1_ERR_RUN ,MOTOR_OFF);
      
        pinMode(DO_BL1_MOTOR_UP, OUTPUT);
        pinMode(DO_BL1_MOTOR_DWN, OUTPUT);
        pinMode(DO_BL1_ERR_RUN, OUTPUT);
      
      //BLIND2
      //TODO: Test extra controller
        pinMode(DI_BL2_UP, INPUT_PULLUP);
        pinMode(DI_BL2_DWN, INPUT_PULLUP);
        //pinMode(AI_BL2_SENS,INPUT_PULLUP);
        //Set outputs to safe state and init
        digitalWrite( DO_BL2_MOTOR_UP,MOTOR_OFF);
        digitalWrite( DO_BL2_MOTOR_DWN,MOTOR_OFF);
        digitalWrite(DO_BL2_ERR_RUN ,MOTOR_OFF);
      
        pinMode(DO_BL2_MOTOR_UP, OUTPUT);
        pinMode(DO_BL2_MOTOR_DWN, OUTPUT);
        pinMode(DO_BL2_ERR_RUN, OUTPUT);
      
      
      
      #if NODE_ID
        gw.begin( incomingMessage, NODE_ID,false); //No repeater NODE_ID is defined
      #else
        gw.begin( incomingMessage);         //No NODE_ID auto from GW (Host) will give you one
      #endif
        gw.sendSketchInfo( SKETCH_NAME, SKETCH_VERSION );
      
        // Register the blind to the gateway
        gw.present( CHILD_ID_SP_BL1, S_DIMMER,"Position" );
        gw.present(CHILD_ID_GAIN_BL1, S_DIMMER, "Gain");
      
        gw.present( CHILD_ID_SP_BL2, S_DIMMER,"Blind 2 Pos" );
        gw.present(CHILD_ID_GAIN_BL2, S_DIMMER, "Blind 2 Gain");
      
        //init the scan clock
        bl_previoustMillis_inp_scan = millis()+1000; //Give a offset from the current moment (1000msec) to complete the setup
      
        //Restore from local EEprom the factor/gain
        int Gain=gw.loadState(EPROM_GAIN_BL1);    //Get the gain from the EEPROM
        Gain = highByte(Gain) ;
        Gain|=  lowByte( gw.loadState(EPROM_GAIN_BL1+1)); //Get the gain from the EEPROM
        blind1.Set_Gain_PV((uint16_t ) Gain);   //Store the gain in controller obj Blind1
        msg.setSensor(CHILD_ID_GAIN_BL1);     //Set startup gain to host
        msg.set(Gain);
        gw.send( msg);                //send it to the host
      
        Gain=gw.loadState(EPROM_GAIN_BL2);      //Get the gain from the EEPROM
        Gain = highByte(Gain);
        Gain|=  lowByte( gw.loadState(EPROM_GAIN_BL2+1)); //Get the gain from the EEPROM
        blind2.Set_Gain_PV((uint16_t ) Gain);   //Store the gain in controller obj Blind1
        msg.setSensor(CHILD_ID_GAIN_BL2);     //Set startup gain to host
        msg.set(Gain);
        gw.send( msg);                //send it to the host
      
      
        // Pull the gateway's current Blind level - restore level upon sender node power-up
        gw.request( CHILD_ID_SP_BL1, V_DIMMER );
      
        // Pull the gateway's current Blind level - restore level upon sender node power-up
        gw.request( CHILD_ID_SP_BL2, V_DIMMER );
      
      
      }
      
      
      void tasks (){
      
        uint8_t tmp_Current , tmp_Current2;
      
        uint8_t tmp_up, tmp_up2;
        uint8_t tmp_dwn , tmp_dwn2;
      
        static uint8_t st_PrevOutput_State  =0; //Local memory only update when something
        static uint8_t st_PrevOutput_State2 =0;
      
        uint8_t  tmp_CurrentOutput_State,tmp_CurrentOutput_State2;
      
        //Read local inputs blind1
        tmp_up = digitalRead(DI_BL1_UP )==false;
        tmp_dwn = digitalRead(DI_BL1_DWN)==false;
      //TODO: Test proof of concept:
        tmp_Current =1;
        // digitalRead(t_BL_InBits::CURSNS)==false;
      
        //Read local inputs blind1
        tmp_up2 = digitalRead(DI_BL2_UP )==false;
        tmp_dwn2 = digitalRead(DI_BL2_DWN)==false;
      
        tmp_Current2 =1;
        //tmp_Current2= analogRead(AI_BL2_SENS) > 100 ? 0 : 1;
      
      
        blind1.bl_SetInputs(tmp_up,tmp_dwn,tmp_Current);
        tmp_CurrentOutput_State =blind1.bl_GetOutputs();
      
        blind2.bl_SetInputs(tmp_up2,tmp_dwn2,tmp_Current2);
        tmp_CurrentOutput_State2 = blind2.bl_GetOutputs();
      
      
        // Somethings changed do actions
        if (st_PrevOutput_State != tmp_CurrentOutput_State){
      
          if (bitRead(tmp_CurrentOutput_State, t_BL_OutBits::BL_RN_ERR )) {
            digitalWrite(DO_BL1_MOTOR_UP,MOTOR_OFF);
            digitalWrite(DO_BL1_MOTOR_DWN,MOTOR_OFF);
            digitalWrite(DO_BL1_ERR_RUN,MOTOR_ON);
      #if DEBUG_BLINDCONTROLLER
            Serial.println("RN_ERR");
      #endif
      
      
          }
          if (bitRead(tmp_CurrentOutput_State, t_BL_OutBits::BL_RN_UP )) {
            digitalWrite(DO_BL1_MOTOR_UP,MOTOR_ON);
            digitalWrite(DO_BL1_MOTOR_DWN,MOTOR_OFF);
      #if DEBUG_BLINDCONTROLLER
            Serial.println("RN_U");
      #endif
      
          }else{
            digitalWrite(DO_BL1_MOTOR_UP,MOTOR_OFF);
      #if DEBUG_BLINDCONTROLLER
            Serial.println("RN_S1");
      #endif
      
          }
      
          if (bitRead(tmp_CurrentOutput_State, t_BL_OutBits::BL_RN_DWN )) {
            digitalWrite(DO_BL1_MOTOR_UP,MOTOR_OFF);
            digitalWrite(DO_BL1_MOTOR_DWN,MOTOR_ON);
      #if DEBUG_BLINDCONTROLLER
            Serial.println("RN_D");
      #endif
      
          }else{
            digitalWrite(DO_BL1_MOTOR_DWN,MOTOR_OFF);
      #if DEBUG_BLINDCONTROLLER
            Serial.println("RN_S2");
      #endif
          }
          st_PrevOutput_State = tmp_CurrentOutput_State;
          if (blind1.Get_PV() >100){
            msg.setSensor(CHILD_ID_SP_BL1);
            msg.setType(V_PERCENTAGE);
      
            gw.send( msg.set(100) );    //Inform the host that we are on the max
            }
          else{
            msg.setSensor(CHILD_ID_SP_BL1);
            msg.setType(V_PERCENTAGE);
            gw.send( msg.set(blind1.Get_PV()) );
          }
      
        }
      
        // Somethings changed for blind2 do actions
        if (st_PrevOutput_State2 != tmp_CurrentOutput_State2){
      
          if (bitRead(tmp_CurrentOutput_State2, t_BL_OutBits::BL_RN_ERR )) {
            digitalWrite(DO_BL2_MOTOR_UP,MOTOR_OFF);
            digitalWrite(DO_BL2_MOTOR_DWN,MOTOR_OFF);
            digitalWrite(DO_BL2_ERR_RUN,MOTOR_ON);
      #if DEBUG_BLINDCONTROLLER
            Serial.println("RNERR2");
      #endif
      
      
          }
          if (bitRead(tmp_CurrentOutput_State2, t_BL_OutBits::BL_RN_UP )) {
            digitalWrite(DO_BL2_MOTOR_UP,MOTOR_ON);
            digitalWrite(DO_BL2_MOTOR_DWN,MOTOR_OFF);
      #if DEBUG_BLINDCONTROLLER
            Serial.println("RNU2");
      #endif
      
          }else{
            digitalWrite(DO_BL2_MOTOR_UP,MOTOR_OFF);
      #if DEBUG_BLINDCONTROLLER
            Serial.println("RNS12");
      #endif
          }
      
          if (bitRead(tmp_CurrentOutput_State2, t_BL_OutBits::BL_RN_DWN )) {
            digitalWrite(DO_BL2_MOTOR_UP,MOTOR_OFF);
            digitalWrite(DO_BL2_MOTOR_DWN,MOTOR_ON);
      #if DEBUG_BLINDCONTROLLER
            Serial.println("RN_D2");
      #endif
      
          }else{
            digitalWrite(DO_BL2_MOTOR_DWN,MOTOR_OFF);
      #if DEBUG_BLINDCONTROLLER
            Serial.println("RNS2");
      #endif
      
          }
          st_PrevOutput_State2 = tmp_CurrentOutput_State2;
          if (blind2.Get_PV() >100){
            msg.setSensor(CHILD_ID_SP_BL2);
            msg.setType(V_PERCENTAGE);
      
            gw.send( msg.set(100) );    //Inform the host that we are on the max
            }
          else{
            msg.setSensor(CHILD_ID_SP_BL2);
            msg.setType(V_PERCENTAGE);
            gw.send( msg.set(blind2.Get_PV()) );
          }
      
        }
      
      
        //Update the eye candy (feedback) Blind1
        if  (blind1.bl_RunErrorLed()  ){
          digitalWrite(DO_BL1_ERR_RUN,MOTOR_ON);
        }else{
          digitalWrite(DO_BL1_ERR_RUN,MOTOR_OFF);
        }
      
        //Update the eye candy (feedback) Blind2
        if  (blind2.bl_RunErrorLed()  ){
          digitalWrite(DO_BL2_ERR_RUN,MOTOR_ON);
        }else{
          digitalWrite(DO_BL2_ERR_RUN,MOTOR_OFF);
        }
      
      }
      
      /**
       * loop - The main program loop
       */
      void loop() {
      
        // Alway process incoming messages whenever possible
        gw.process();
      
        blind1.bl_Process();
        blind2.bl_Process();
      
        tasks();
      
      }
      
      
      
      /**
       * incomingMessage - Process the incoming messages
       * From the host
       */
      void incomingMessage( const MyMessage &message ) {
        uint16_t tmp_Faktor;
      
        uint8_t New_sp =0;
        uint8_t New_Cmd=0;
      
        if (message.sensor ==CHILD_ID_SP_BL1 ) {
          if (message.type == V_DIMMER) { // This is a SP change request
              int val = message.getInt();//retrieve SP from message
              bitSet(New_Cmd,0);
              New_sp = 0xff & val; //set SP to the requested value
      
            }else if (message.type==V_STATUS) {//Position request (full open / full closed)
                  if (!message.getBool()) { //I Use a inverted blind on the GUI
                    bitSet(New_Cmd,1);    //Fire to full close
               }else{
                 bitSet(New_Cmd,2);       //Fire to full open
               }
            }
            blind1.UpdateRemote_cmd(New_sp,New_Cmd);//Send it to the controller
      
        }else if (message.sensor ==CHILD_ID_GAIN_BL1 ){
            tmp_Faktor = message.getInt();
            if(tmp_Faktor != 0)
              blind1.Set_Gain_PV(tmp_Faktor);
              gw.saveState(EPROM_GAIN_BL1,highByte( tmp_Faktor));
              gw.saveState(EPROM_GAIN_BL1+1,lowByte( tmp_Faktor));
      
        }else if (message.sensor ==CHILD_ID_SP_BL2 ){
          if (message.type == V_DIMMER) { // This is a SP change request
              int val = message.getInt();//retrieve SP from message
              bitSet(New_Cmd,0);
              New_sp = 0xff & val; //set SP to the requested value
      
            }else if (message.type==V_STATUS) {//Position request (full open / full closed)
                  if (!message.getBool()) { //I Use a inverted blind on the GUI
                    bitSet(New_Cmd,1);    //Fire to full close
               }else{
                 bitSet(New_Cmd,2);       //Fire to full open
               }
            }
            blind2.UpdateRemote_cmd(New_sp,New_Cmd);//Send it to the controller
      
        }else if (message.sensor ==CHILD_ID_GAIN_BL2 ){
      
            tmp_Faktor = message.getInt();
            if(tmp_Faktor != 0)
            blind2.Set_Gain_PV(tmp_Faktor);
            gw.saveState(EPROM_GAIN_BL2,highByte( tmp_Faktor));
            gw.saveState(EPROM_GAIN_BL2+1,lowByte( tmp_Faktor));
          }
      
      }
      
      

      Header file ""Rfm69_BlindController.h"

      
      // Only modify this file to include
      // - function definitions (prototypes)
      // - include files
      // - extern variable definitions
      // In the appropriate section
      
      #ifndef _BlindController_H_
      #define _BlindController_H_
      #include "Arduino.h"
      //add your includes for the project BlindController here
      
      #include "MySensor.h"
      
      //end of add your includes here
      
      
      
      
      
      
      
      //Do not add code below this line
      #endif /* _BlindController_H_ */
      
      
      posted in My Project
      stedew
      stedew
    • RE: Sensebender with RFM69

      Well i don't know wich RFM69 you use but i have here a few moteino's and also toy-ing with them i had similar problem no data exchange possible between the two moteino's. whatever i try no connection was builtup. i even unsolder a rfm69HW on the GW and replaced it.. it communicates??? So conclusion bad RFM69 Throw away.. and test further. After a few days again same problem. Now it was on the breadboard so replacing was easy. Same as before (replace and works).
      Then i loaded up the moteino test program in the sensornode and the GW with the non working RFM69 .... Works like a charm??? switch back to Mysensors works again.. I Can't remeber anymore what i did but you have to look at the code n the utility folder the rfm69.cpp file in the initializer. when there is no encryption (NULL) the encryption string is not written.. so ones it's filled in you can't clear it. I suspect that the problem relies there..
      regards, Stefan.

      posted in Hardware
      stedew
      stedew