Can I modify an X-10 Appliance module to use a duty cycle. Answered

I need to modify an X-10 appliance module so it will turn on when activated with the motion sensor but the modification I need is to limit the ON time to a duty cycle.   Here's the reason.  I use an X-10 Eagle Eye motion sensor to activate a recirculating hot water system.  In the morning, the motion sensor is activated, the recirc pump turns on and my solar hot water tank is circulated throughout the house.   There are (2) problems with the stock circuit. 1) the appliance module sometimes stays on randomly and can drain the hot water tank overnight, or worse, trigger the electric heat and run up a huge bill. So, the Appliance module definitely needs a forced cycle at that unit to prevent running continuously.  2) when people are always in the room with the motion sensor, the pump only needs to stay on for a few minutes per hour to keep hot water in the recirculation system, but when motion activity is continuous then the motion sensor stays on and triggers the circulation pump to run continuously thereby draining the solar tank needlessly.   I've believed X-10 could do well by adding a duty cycle to the module but maybe someone here has the ability to guide me how to do this.  My duty cycle would be something like 3 minutes per 60, for example and preferably adjustable so other applications can use it.  So, once activated by an X-10 signal, the appliance module would run no more than duty cycle allows regardless of the motion sensor commands.  However, if the motion sensor commands OFF I suppose that makes sense to continue to use that command. My preference is to put the components inside the X-10 Appliance module if that is possible and safe.  Putting controls in the Motion sensor does not prevent the pump running beyond the duty cycle and adding PCs or other controller boxes is not desired.   However, if a microcontroller would work and fit then I think it could be the basis for a much more functional X-10 module.  I've researched the other Appliance Module modifications but so far I don't see anything that would extend to this feature.   I do appreciate your ideas so thanks in advance.

Question by solarwater   |  last reply


500W electric scooter control and instrumentation with Arduino mega

1. Introduction DC 500W motor control with an Arduino mega to limit starting current and to vary the speed of the scooter. The battery is in 24V, 10A.h. The following table summarizes their characteristics: https://i58.servimg.com/u/f58/17/56/35/17/a014.jpg https://i58.servimg.com/u/f58/17/56/35/17/a111.jpg 2. Bibliography: Link download : sketch_escooter_feed_back_reel_V1.ino https://drive.google.com/file/d/0B_fB3GAsM02FSlRTWHdyRkhuUW8/view?usp=sharing escooter_ampli_SIMULINK.mdl https://drive.google.com/file/d/0B_fB3GAsM02FOW9OdmlhdDhJZGc/view?usp=sharing escooter feed back ISIS.DSN https://drive.google.com/file/d/0B_fB3GAsM02FOXdRWFN5OWRMQkE/view?usp=sharing youtube  :  "study trotinette electric e-scooter 100W et 350W, wiring"  youtube https://www.youtube.com/watch?v=QqJ2-YiE8Tg&index;=75&list;=PLfZunVn_gcq7EOurXuWU2sRFmh6CbiUiL Article: «Study of electric scooters 100W and 500W (Arduino), Revue 3EI 2017» Pdf? Book «I realize my electric vehicle» at DUNOD 3. Open loop program To test the programming, we simulate the program in ISIS, as can be seen in the following figure. In addition, we have an LCD display to display data (duty cycle corresponding to the PWM at 32Khz, motor current, motor voltage, action on the pushbuttons, 4 push buttons are used. BP1 to manually increment the duty cycle, BP2 decrement it. BP3 set the duty cycle to 0, corresponding to the brake contact. The speed of the motor is practically proportional to the duty cycle https://i58.servimg.com/u/f58/17/56/35/17/a211.jpg We made our own current amplifier called a step-down chopper but it is possible to buy a shield There are many cards for Arduino to control DC motors especially of low powers and also of great powers as can be observed on the following links.http://www.robotpower.com/products/MegaMotoPlus_info.html http://www.robotshop.com/en/dc-motor-driver-2-15a.html https://www.pololu.com/file/0J51/vnh3sp30.pdf https://i58.servimg.com/u/f58/17/56/35/17/a310.jpg But all these chopper shields measure the current internally but there is no current limitation. In order to have a current limitation, an analog current loop is required using specialized AOP or IC or a fast digital current loop. But what should be the value of the limitation current? The choice of the current value is normally for the 1-hour operation service in order to be able to carry out relatively long climbs without reaching the critical temperature of the engine. In our case, the limitation current must be Limiting motor = Power / Upper battery = 500W / 24V = 20A In addition, the power transistor of the chopper can only support 50A in our case. But in open loop, it has no current regulation, so as not to exceed the maximum current, a ramp of the duty cycle will be used. A 0.1 second interruption routine will be used to measure the voltage of the current (sample measurement, sample). This sampling time is arbitrary but does not allow to be faster than the rise time of the current because the electric time constant of the motor is L / R = 1.5 ms. Open loop operation with a 25.5s (8bit) ramp and 0.1s interrupt routine provides a good understanding of the operation of a DC motor drive. The display will only be done every 0.2s to have a stability of the digits on the screen. In addition, a digital filtering will be done on the current and the voltage on 4 values therefore on 0.4s. [b] Algo open loop [/b] Interrupt Routine All 0.1S Read voltage and current Loop loop (push button scan) If BP1 = 1 then increment PWM If BP2 = 1 then decrement PWM If BP3 = 1 then PWM = 0 Displaying variables every 0.2s Code: [Select] // include the library code: #include #include #include #define SERIAL_PORT_LOG_ENABLE 1 #define Led     13       // 13 for the yellow led on the map #define BP1     30       // 30 BP1 #define BP2     31       // 31 BP2           #define BP3     32       // 32 BP3 #define LEDV    33       // 33 led #define LEDJ    34       // 34 led #define LEDR    35       // 35 led #define relay   36       // 36 relay #define PWM10    10      //11   timer2    LiquidCrystal lcd(27, 28, 25, 24, 23, 22); // RS=12, Enable=11, D4=5, D5=4, D6= 3, D7=2, BPpoussoir=26 // Configuring variables unsigned   int UmoteurF = 0;  // variable to store the value coming from the sensor unsigned   int Umoteur = 0; unsigned   int Umoteur2 = 0; unsigned   int Umoteur3 = 0; unsigned   int Umoteur4 = 0; unsigned   int ImoteurF = 0;  unsigned   int Imoteur = 0; unsigned   int Imoteur2 = 0; unsigned   int Imoteur3 = 0; unsigned   int Imoteur4 = 0;            byte Rcy=0 ;    // 8bit duty cycle unsigned    int temps; // the setup function runs once when you press reset or power the board void setup() {   pinMode(Led, OUTPUT);   // Arduino card   pinMode(LEDV, OUTPUT);   pinMode(LEDR, OUTPUT);   pinMode(LEDJ, OUTPUT);   pinMode (PWM10,OUTPUT);     // Pin (10) output timer2   //  digitalWrite(LEDV,LOW);   Timer1.initialize(100000);         // initialize timer1, and set a 0,1 second period =>  100 000   Timer1.attachInterrupt(callback);  // attaches callback() as a timer overflow interrupt   lcd.begin(20, 4);    Serial1.begin(9600);   TCCR2B = (TCCR2B & 0b11111000) | 0x01;         //pin 10  32khz    http://playground.arduino.cc/Main/TimerPWMCheatsheet                                                   //http://www.pobot.org/Modifier-la-frequence-d-un-PWM.html   //   analogWriteResolution(bits)      https://www.arduino.cc/en/Reference/AnalogWriteResolution lcd.setCursor(0,1); lcd.print("Rcy"); lcd.setCursor(10,1); lcd.print("Um"); lcd.setCursor(5,1); lcd.print("Im"); lcd.setCursor(10,1); lcd.print("Um"); lcd.setCursor(20,1); // 4 lines display * 20 characters lcd.print("BP1+"); lcd.setCursor(25,1); lcd.print("BP2-"); lcd.setCursor(29,1); lcd.print("BP3=0"); } // Interruptions  tous les 0.1s void callback()  { temps++; //toogle state ledv for check   if ( digitalRead(LEDV)== 1 ) {digitalWrite(LEDV,LOW);}     else {digitalWrite(LEDV,HIGH);}     analogWrite(PWM10,Rcy);   // frequency Umoteur=analogRead(A0); Imoteur=analogRead(A1); Imoteur2=Imoteur; Imoteur3=Imoteur2; Imoteur4=Imoteur3; ImoteurF=(Imoteur4+Imoteur3+Imoteur2+Imoteur)/4 ; Umoteur2=Umoteur; Umoteur3=Umoteur2; Umoteur4=Umoteur3; UmoteurF=(Umoteur4+Umoteur3+Umoteur2+Umoteur)/4 ;   }// End routine // Loop corresponding to main function void loop() {    // BP + LED   if ((digitalRead(BP1))==1) {     lcd.setCursor(20,0);      // Column line     lcd.print("BP1");     digitalWrite(LEDR, LOW);        digitalWrite(LEDJ, LOW);     Rcy++;                        // PWM incrementation     if ( Rcy>254)  {Rcy=254;}     delay(100);               //8bits * 100ms = 25S increment 25ssecond slope     }        if ((digitalRead(BP2))==1) {     lcd.setCursor(20,0);     lcd.print("BP2");             Rcy--;      if ( Rcy<2)  {Rcy=2;}  // PWM almost at 0, engine stop         delay(100);      digitalWrite(LEDR, HIGH);     digitalWrite(LEDJ, HIGH);     }   if ((digitalRead(BP3))==1) {     lcd.setCursor(20,0);     lcd.print("BP3");      Rcy=2;               // PWM almost at 0, engine stop     } if (temps>=2)  { lcd.setCursor(0,0); lcd.print("                "); // Erase line lcd.setCursor(0,0);     lcd.print(Rcy); lcd.setCursor(5,0); ImoteurF=(ImoteurF)/20;     //resistance (5/1024)*(10/0.25ohm) si ACS712 66mV/A                            // For resistance 1ohm (ImoteurF) / 20; Simulation 5/25 lcd.print(ImoteurF); lcd.setCursor(10,0); UmoteurF=UmoteurF*10/38;                              //10/38   10/30 simula if (Umoteur>ImoteurF){UmoteurF=UmoteurF-ImoteurF;  }  //U-R*I lcd.print(UmoteurF); temps=0; }// End if time    } // End loop https://i58.servimg.com/u/f58/17/56/35/17/dsc_0614.jpg Since there is a limit of 9000 characters in the forum below Open loop program feature previous The interrupt routine lasts only 250 microseconds, the loop of the main program which scans the action of push buttons is 13micros and the display time of all data is 11ms. Thus, it is possible to improve the sampling period and thus the speed of the regulation of the current. The Arduino makes it possible to make the instrumentation of the scooter so to know the power, the consumption in Ah and Wh, to measure the speed, to know the consumption according to Wh / km, to measure the temperature of the engine, Have a safe operation. But for now we will see how to limit the current 4. Closed loop program, limited current control The sampling period will increase to 0.01 seconds (interrupt routine) If the current is less than the desired value, then the duty cycle can be increased or decreased to the desired value which is the setpoint. On the other hand, if the motor current is greater than the limiting value, there is a rapid decrease in the duty cycle. So as not to exceed the value of the duty cycle if it is saturated to 254 maximum and to the minimum value 6. Code: [Select] if (Imoteur<4000)                    // No current limitation at (20A * 10) * 20 = 4000   {if (consigne>Rcy)   {Rcy=Rcy+1;}   // Pwm ramp + 1 * 0.01second pure integrator    if (consigne    if ( Rcy>254)  {Rcy=254;}           // Limitation of duty cycle    analogWrite(PWM10,Rcy);   // Frequency 32kHz timer2}         } if (Imoteur>4000)  { Rcy=Rcy-5;              // No current filtering, to be faster                     if ( Rcy<6)  {Rcy=5;}       // Rcy is not signed, nor the PWM therefore Rcy minimum must not be less than 6                   analogWrite(PWM10,Rcy);   // Frequency 32kHz timer2}                        } 5. Closed Loop Program, Limited Current Control with Acceleration Handle An acceleration handle provides a 0.8V voltage when not operated and a 4.5V voltage when the handle is fully engaged. Instead of using pushbuttons to increase or decrease the speed setpoint, an acceleration handle will be used Code: [Select] Upoignee=analogRead(A3); // The relation in Upoign and the setpoint which corresponds to the duty cycle corresponds to if (Upoignee>100) { consigne=(Upoignee/2);     //0=a*200+b    et 255=a*800+b                      consigne= consigne-100;                   }                            else { consigne=0;   }               if (Upoignee<100) { consigne=0;  }     // redundancy     6. Temperature and safety program of the motor with the current measurement The outdoor temperature measurement can be easily performed by the LM35 component which charges 0.01V by degrees Celsius Code: [Select] temperature=analogRead(A2); //lm35 0.01V/°C temperature=temperature/2;       // Temperature coefficient lcd.setCursor(5,2); lcd.print("      "); lcd.setCursor(5,2); lcd.print(temperature);   // Display in ° C lcd.setCursor(9,2);      // Erasing secu display lcd.print("     ");   if (temperature>80 ) {lcd.setCursor(9,2);         // If motor external temperature is above 80 ° C                      lcd.print("secuT");                       Rcy=0;} In addition, thermal safety by measuring the motor current will be added. If the limitation current is greater than 10s then the motor will no longer be powered for 30s. A "secu" display will appear on the LCD display. This safety makes it possible to cut the motor on slope too high and when blocking the engine but it would be necessary to add the measurement of the speed in the latter case Code: [Select] if (timesecurite>=10000 ) {flagarret=1;      // If limitation current for a current of more than 10s                               timerepos=0;                               consigne=0;                               Rcy=0;                                 timesecurite=0;}       //   Then stop engine during a downtime    if (flagarret==1 ) {lcd.setCursor(9,2);         // If limiting current for a current of more than 20s                      lcd.print("secU");  }     //   Then stopping the motor for a stop time and display                                                     if (timerepos>=30000 &&  flagarret==1) {flagarret=0;                                           lcd.setCursor(9,2);      // After a rest time here of 30s                                            lcd.print("       ");   }   The display can be observed if the temperature is above 80 ° C https://i58.servimg.com/u/f58/17/56/35/17/a017.jpg Thermal safety by measuring the motor current (digital thermal relay) which allows to know the image of the internal temperature of the engine would be ideal. But for this, it is necessary to know well the thermal modeling of the motor. 7. Measurement of the energy capacity of the battery The energy capacity of a battery is in A.H, we will display the value in mA.H to have a high accuracy. The capacity will be in A.Second in the following equation. So to have in mA.H, it will be divided by capacity by3600. Capacity (A.s) n = I * Te + Cn-1 with Te = 0.01s and I multiplied by 10 So in the interrupt routine Code: [Select] capacity=ImoteurF+capacity ; And in the display Code: [Select] lcd.setCursor(0,3); // Display of energy capacity lcd.print("C mA.h="); capacity1=capacity/(18000);   //18000=3600*5  5=> Current measurement coefficient lcd.print(capacity1); To check a current of 10A with an adjustable resistor and after 30s, the capacity must be 83mA.H 8. Power and modeling with SIMULINK Modeling helps to understand the vehicle and its control. In addition, it is possible to compile the control part directly into the Arduino program from simulation under Simulink. But it will not be possible to simulate the instrumentation with the LCD display. In the following figure, we can observe the simulation of the programming of the chopper with the current limitation with Simulink. In the following figure, the green box shows the duty cycle control to vary the speed and the red border the current limitation. The controller of the control is here a simple integrator but it is possible to carry out a multitude of control. https://i58.servimg.com/u/f58/17/56/35/17/azub_c15.jpg In the previous figure, it can be observed that the current is well limited to 25A from 2s to 9.5s. Then, the current reaches 10.8A under established speed regime at 22.5km / h. The dynamics are similar to the tests carried out. With a slope of 5%, the cyclic ratio reaches only 100% as can be seen in the following figure. The speed will reach painfully 19km / h with a current of 24A and a motor power of 580W. See article: Study of electric scooters 100W and 500W (Arduino), 9. First conclusion It is easy to control a 500W DC motor with an Arduino and some components So repair many scooters that are in DC motors. But it takes some knowledge (automatic, engine) to know how to properly manage the engine and limit its current so as not to damage it The display of the speed, the distance, the operating time to know the Watt.km / km can also be realized with a menu 2. The .ino program as an attached file, But it is not possible to put an attached file in ISIS electronic labcenter? What is this forum? It would be desirable that the compiler could generate the.cof to debug in Isis and test the program line by line .... Arduino still has to make a lot of effort to be on the same level as other microcontrollers 10. speed measurement (tachometer) Velocity measurement is carried out using a hall effect sensor SS495 or A1324 which counts each revolution of the wheel. It is enough to enter the perimeter of the wheel of the scooter (130mm of radius therefore 0.816m in the case To have the speed, it is enough just to divide the number of turn of wheel on an arbitrary time of 1s to have a minimum speed of 0.81m / s therefore of 2.93 km / h. In addition, an average filter with 3 values will be used to display the speed. At 25km / h, there will be 8.5 laps. To count the turns, an external interrupt routine will be used on input INT0 21 of the mega card. http://www.locoduino.org/spip.php?article64 To simulate the speed, a pulse on input 21 will be used with a duty cycle of 10%. https://i58.servimg.com/u/f58/17/56/35/17/a018.jpg Code: [Select] void INT0b21() {   Tspeed++;   // External interruption to count the number of turns } // In the set up declare the interrupt routine when the 5V edge of the magnet detection is done   attachInterrupt(digitalPinToInterrupt(21), INT0b21, RISING );  // External interruption // In loop if (temps09>=5)  {        // 1 second loop lcd.setCursor(13,2);      // Erasing speed lcd.print("kph     "); lcd.setCursor(16,2); speed1=Tspeed*2937;      //1tour*816*3.6/1s=2.937km/h speed2=speed1;           //Tspeed (rate/seconde) speed3=speed2; speedF=(speed1+speed2+speed3)/3000;   // To put in kph lcd.print(speedF,1);    // Display to the nearest tenth Tspeed=0;   // Reset counter temps09=0;  //reset time } To improve the accuracy of the velocity measurement, it is possible that the sampling time of the velocity measurement is dependent on the velocity. For example: For speeds less than 10km / h sample at 1second, but above 10km / h sample at 2 seconds. 11. Distance measurement for autonomy The distance corresponds to the total number of turns of the wheel multiplied by the perimeter of the wheel. So do not set the number of turns to 0 for each sample. On the other hand, the reset of the distance will be done when pressing the reset of the Arduino Mega. The distance display will be displayed to the nearest second. At 32km / h, it will take 2 minutes to do 1km as can be seen in the following figure: https://i58.servimg.com/u/f58/17/56/35/17/a019.jpg Code: [Select] void INT0b21() {   Tspeed++;   // External interruption to count speed   nbrRate++; } lcd.setCursor(13,4);      lcd.print("km      ");  // distance=(nbrRate*816)/1000;  //distance m distance=distance/1000;  //distance km lcd.setCursor(15,4);      lcd.print(distance,1);  You can observe the electrical installation with the chopper, the arduino, and the display when the program is set up https://i58.servimg.com/u/f58/17/56/35/17/dsc_0613.jpg 12. Synthesis The RAM space is used only at 4% and ROM space at 3%, for an Arduino mega. So we could take an arduino a little smaller. But, there are 8 Lipo cells to make the 24V power supply to power the engine via the chopper. Therefore, the voltage measurement of each element will be on the Arduino with a JST connector. This measurement makes it possible to know if a cell with an internal resistance which begins to pose a problem and to know if the balancing of each cell has indeed been carried out. It is possible to switch to 36V with 12 cells also with the arduino mega without using an external shield that multiplex 24 analog inputs on input A0 It is possible to send all data to a smartphone via Bluetooth HC06 via pins 20, 21, RX1 and TX1. But the application under android realized under JAVA Studio can not be shared on this forum. This part will not be explained. After having made the instrumentation of this scooter, a study should be carried out on the precision of the measurements, it is possible to read "Instrumentation of a low-power electrical motor vehicle" eco marathon "type Revue 3EI N ° 81, July 2015 http://www.fichier-pdf.fr/2015/09/07/instrumentation-vehicule-faible-consommation-eco-marathon/

Topic by Iutgeiisoissons 


I have a problem in this code for Arduino UNO , Can you help me?

#include #include #define SOL_ADC A0     // Solar panel side voltage divider is connected to pin A0 #define BAT_ADC A1    // Battery side voltage divider is connected to pin A1 #define CURRENT_ADC A2  // ACS 712 current sensor is connected to pin A2 #define TEMP_ADC A3   // LM 35 Temperature is connected to pin A3 #define AVG_NUM 10    // number of iterations of the adc routine to average the adc readings #define BAT_MIN 10.5  // minimum battery voltage for 12V system #define BAT_MAX 15.0  // maximum battery voltage for 12V system #define BULK_CH_SP 14.4 // bulk charge set point for sealed lead acid battery // flooded type set it to 14.6V #define FLOAT_CH_SP 13.6  //float charge set point for lead acid battery #define LVD 11.5          //Low voltage disconnect setting for a 12V system #define PWM_PIN 3         // pin-3 is used to control the charging MOSFET //the default frequency is 490.20Hz #define LOAD_PIN 2       // pin-2 is used to control the load #define BAT_RED_LED 5 #define BAT_GREEN_LED 6 #define BAT_BLUE_LED 7 #define LOAD_RED_LED 8 #define LOAD_GREEN_LED 9 //-------------------------------------------------------------------------------------------------------------------------- ///////////////////////DECLARATION OF ALL BIT MAP ARRAY FOR FONTS//////////////////////////////////////////////////////////////// //-------------------------------------------------------------------------------------------------------------------------- byte solar[8] = //icon for solar panel {   0b11111,0b10101,0b11111,0b10101,0b11111,0b10101,0b11111,0b00000 }; byte battery[8] =  //icon for battery {   0b01110,0b11011,0b10001,0b10001,0b10001,0b10001,0b10001,0b11111 }; byte energy[8] =  // icon for power {   0b00010,0b00100,0b01000,0b11111,0b00010,0b00100,0b01000,0b00000 }; /*byte alarm[8] =  // icon for alarm { 0b00000,0b00100,0b01110,0b01110,0b01110,0b11111,0b00000,0b00100 };*/ byte temp[8] = //icon for termometer { 0b00100,0b01010,0b01010,0b01110,0b01110,0b11111,0b11111,0b01110 }; byte charge[8] = // icon for battery charge {   0b01010,0b11111,0b10001,0b10001,0b10001,0b01110,0b00100,0b00100, }; byte not_charge[8]= {   0b00000,0b10001,0b01010,0b00100,0b01010,0b10001,0b00000,0b00000, }; //-------------------------------------------------------------------------------------------------------------------------- ///////////////////////DECLARATION OF ALL GLOBAL VARIABLES////////////////////////////////////////////////////////////////// //-------------------------------------------------------------------------------------------------------------------------- float solar_volt=0; float bat_volt=0; float load_current=0; int temperature=0; int temp_change=0; float system_volt=0; float bulk_charge_sp=0; float float_charge_sp=0; float charge_status=0; float load_status=0; float error=0; float Ep=0; int duty =0; float lvd; float msec=0; float last_msec=0; float elasped_msec=0; float elasped_time=0; float ampSecs = 0; float ampHours=0; float watts=0; float wattSecs = 0; float wattHours=0; // Set the pins on the I2C chip used for LCD connections: //                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address // In my case 0x27 //******************************************************* MAIN PROGRAM START ************************************************ void setup() { Serial.begin(9600); pinMode(BAT_RED_LED,OUTPUT); pinMode(BAT_GREEN_LED,OUTPUT); pinMode(BAT_BLUE_LED,OUTPUT); pinMode(LOAD_RED_LED ,OUTPUT); pinMode(LOAD_GREEN_LED,OUTPUT); pinMode(PWM_PIN,OUTPUT); pinMode(LOAD_PIN,OUTPUT); digitalWrite(PWM_PIN,LOW);  // default value of pwm duty cycle digitalWrite(LOAD_PIN,LOW);  // default load state is OFF lcd.begin(20,4);   // initialize the lcd for 16 chars 2 lines, turn on backlight lcd.backlight(); // finish with backlight on  lcd.createChar(1,solar); lcd.createChar(2, battery); lcd.createChar(3, energy); //lcd.createChar(4,alarm); lcd.createChar(5,temp); lcd.createChar(6,charge); lcd.createChar(7,not_charge); lcd.clear(); } void loop() { read_data();             // read different sensors data from analog pin of arduino system_voltage();        // detect the system voltage according to battery voltage setpoint();      // decide the charge set point according to system voltage charge_cycle();         // pwm charging of battery power();                // calculate the load power and energy load_control();         //control the load led_indication();       // led indica print_data();            // print in serial monitor lcd_display();           // lcd display } //************************************************************ PROGRAM END ************************************************* //------------------------------------------------------------------------------------------------------ ////////////////// READS AND AVERAGES THE ANALOG INPUTS (SOLRAR VOLTAGE,BATTERY VOLTAGE)//////////////// //------------------------------------------------------------------------------------------------------ int read_adc(int adc_parameter) {     int sum = 0;   int sample ;   for (int i=0; i   {                                        // loop through reading raw adc values AVG_NUM number of times      sample = analogRead(adc_parameter);    // read the input pin      sum += sample;                        // store sum for averaging     delayMicroseconds(50);              // pauses for 50 microseconds    }   return(sum / AVG_NUM);                // divide sum by AVG_NUM to get average and return it } //------------------------------------------------------------------------------------------------------------- ////////////////////////////////////READ THE DATA////////////////////////////////////////////////////////////// //------------------------------------------------------------------------------------------------------------- void read_data(void) {     //5V = ADC value 1024 => 1 ADC value = (5/1024)Volt= 0.0048828Volt     // Vout=Vin*R2/(R1+R2) => Vin = Vout*(R1+R2)/R2   R1=100 and R2=20      solar_volt = read_adc(SOL_ADC)*0.00488*(120/20);      bat_volt   = read_adc(BAT_ADC)*0.00488*(120/20);            load_current = (read_adc(CURRENT_ADC)*.0488 -25);      temperature = read_adc(TEMP_ADC)*0.00488*100;        }   //------------------------------------------------------------------------------------------------------------ /////////////////////////////////POWER AND ENERGY CALCULATION ////////////////////////////////////////////// //------------------------------------------------------------------------------------------------------------ void power(void) { msec = millis(); elasped_msec = msec - last_msec; //Calculate how long has past since last call of this function elasped_time = elasped_msec / 1000.0; // 1sec=1000 msec watts = load_current * bat_volt; //Watts now ampSecs = (load_current*elasped_time); //AmpSecs since last measurement wattSecs = ampSecs * bat_volt; //WattSecs since last measurement ampHours = ampHours + ampSecs/3600; // 1 hour=3600sec //Total ampHours since program started wattHours = wattHours + wattSecs/3600; // 1 hour=3600sec //Total wattHours since program started last_msec = msec; //Store 'now' for next time } //------------------------------------------------------------------------------------------------------------ /////////////////////////////////PRINT DATA IN SERIAL MONITOR///////////////////////////////////////////////// //------------------------------------------------------------------------------------------------------------   void print_data(void)   {     delay(100);     Serial.print("Solar Panel Voltage: ");     Serial.print(solar_volt);     Serial.println("V");     Serial.print("Battery Voltage: ");     Serial.print(bat_volt);     Serial.println("V");     Serial.print("Syestem Voltage: ");     Serial.print(system_volt);     Serial.println("V");     Serial.print("Charge Set Point:");     Serial.println(bulk_charge_sp);     Serial.print("Temperature:");     Serial.print(temperature);     Serial.println("C");     Serial.print("Load Current: ");     Serial.print(load_current);     Serial.println("A");     Serial.print("Power: ");     Serial.print(watts);     Serial.println("W");     Serial.print("Energy: ");     Serial.print(wattHours);     Serial.println("WH");     Serial.print("Duty Cycle :");     if (charge_status==1)     {     Serial.println("99%");     Serial.println("BULK CHARGING");     }     else if (charge_status==2)     {     Serial.print(Ep);     Serial.println("%");     Serial.println("FLOAT CHARGING");     }     else     {     Serial.println("0%");     Serial.println("NOT CHARGING");     }     if(load_status==1)     {      Serial.println("LOAD IS CONNECTED");     }     else     {      Serial.println("LOAD IS DISCONNECTED");       }        Serial.println("***************************"); } //---------------------------------------------------------------------------------------------------------------------- //////////////////////////////////SYSTEM VOLTAGE AUTO DETECT /////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------------------------------------------- void system_voltage(void) {   if ((bat_volt >BAT_MIN) && (bat_volt < BAT_MAX))   {      system_volt = 12;   }   /*   else if  ((bat_volt > BAT_MIN*2 ) && (bat_volt < BAT_MAX*2))   {     system_volt=24;   }*/   else if ((bat_volt > BAT_MIN/2 ) && (bat_volt < BAT_MAX/2))   {     system_volt=6;   }   } //--------------------------------------------------------------------------------------------------------------------------- ////////////////////////////////////CHARGE SET POINT /////////////////////////////////////////////////////////////////////// //--------------------------------------------------------------------------------------------------------------------------- void setpoint(void) {   temp_change =temperature-25.0; // 25deg cel is taken as standard room temperature // temperature compensation = -5mv/degC/Cell   // If temperature is above the room temp ;Charge set point should reduced   // If temperature is bellow the room temp ;Charge set point should increased   if(system_volt ==12)   {      bulk_charge_sp = BULK_CH_SP-(0.030*temp_change) ;      float_charge_sp=FLOAT_CH_SP-(0.030*temp_change) ;      lvd =LVD;   }   else if(system_volt ==6)   {      bulk_charge_sp = (BULK_CH_SP/2)-(0.015*temp_change) ;      float_charge_sp= (FLOAT_CH_SP/2)-(0.015*temp_change) ;      lvd=LVD/2;   }   /*   else if (system_volt == 24)   {    bulk_charge_sp = (BULK_CH_SP*2)-(0.060*temp_change) ;    float_charge_sp= (FLOAT_CH_SP*2)-(0.060*temp_change) ;    lvd=LVD*2;   }   */   } //-------------------------------------------------------------------------------------------------------------------------------- ///////////////////////////////////////////////////PWM CHARGE CYCLE @500 HZ ////////////////////////////////////////////////// //------------------------------------------------------------------------------------------------------------------------------- void charge_cycle(void) {   if (solar_volt > bat_volt && bat_volt <= bulk_charge_sp)   {         if (bat_volt <= float_charge_sp) // charging start   {       charge_status = 1; // indicate the charger is in BULK mode      duty= 252.45;      analogWrite(PWM_PIN,duty); // 99 % duty cycle // rapid charging           }   else if (bat_volt >float_charge_sp && bat_volt <= bulk_charge_sp)   {         charge_status = 2; // indicate the charger is in FLOAT mode       error  = (bulk_charge_sp - bat_volt);      // duty cycle reduced when the battery voltage approaches the charge set point       Ep= error *100 ; //Ep= error* Kp // Assume  Kp=100             if(Ep < 0)        {         Ep=0;         }       else if(Ep>100)         {          Ep=100;         }       else if(Ep>0 && Ep <=100) // regulating        {          duty = (Ep*255)/100;        }        analogWrite(PWM_PIN,duty);    } }    else    {    charge_status=0;  // indicate the charger is OFF    duty=0;    analogWrite(PWM_PIN,duty);    } } //---------------------------------------------------------------------------------------------------------------------- /////////////////////////////////////////////LOAD CONTROL///////////////////////////////////////////////////// //----------------------------------------------------------------------------------------------------------------------    void load_control() { if (solar_volt < 5  ) // load will on when night {   if(bat_volt >lvd)   // check if battery is healthy   {   load_status=1;   digitalWrite(LOAD_PIN, HIGH); // load is ON   }   else if(bat_volt < lvd)   {     load_status=0;    digitalWrite(LOAD_PIN, LOW); //load is OFF   } } else // load will off during day {    load_status=0;    digitalWrite(LOAD_PIN, LOW); } } //------------------------------------------------------------------------------------------------- //////////////////////////LED INDICATION//////////////////////////////////// //------------------------------------------------------------------------------------------------- void led_indication(void) {   battery_led();           //Battery status led indication   load_led();              //Load led indication } //---------------------------------------------------------------------------------------------------------------------- /////////////////////////////////////////////BATTERY LED INDICATION///////////////////////////////////////////////////// //---------------------------------------------------------------------------------------------------------------------- void battery_led(void) {      if( (bat_volt > system_volt) && ( bat_volt   {         leds_off_all();       digitalWrite(BAT_GREEN_LED,LOW);  // battery voltage is healthy   }   else if(bat_volt >= bulk_charge_sp)   {       leds_off_all();       digitalWrite(BAT_BLUE_LED,LOW);  //battery is fully charged   }    else if(bat_volt < system_volt)   {       leds_off_all();       digitalWrite(BAT_RED_LED,LOW);  // battery voltage low   } } //---------------------------------------------------------------------------------------------------------------------- /////////////////////////////////////////////LOAD LED INDICATION///////////////////////////////////////////////////// //----------------------------------------------------------------------------------------------------------------------      void load_led()   {     if(load_status==1)     {       digitalWrite(LOAD_GREEN_LED,HIGH);     }     else if(load_status==0)     {       digitalWrite(LOAD_RED_LED,HIGH);     }    } //------------------------------------------------------------------------------------------------------ //////////////////////// TURN OFF ALL THE LED/////////////////////////////////////////////////////////// //------------------------------------------------------------------------------------------------------ void leds_off_all(void) {     digitalWrite(BAT_RED_LED,HIGH);   digitalWrite(BAT_GREEN_LED,HIGH);   digitalWrite(BAT_BLUE_LED,HIGH);   digitalWrite(LOAD_RED_LED, LOW);   digitalWrite(LOAD_GREEN_LED, LOW); } //------------------------------------------------------------------------------------------------------ //////////////////////// LCD DISPLAY/////////////////////////////////////////////////////////// //------------------------------------------------------------------------------------------------------ void lcd_display() { lcd.setCursor(0, 0); lcd.write(1); lcd.setCursor(2, 0); lcd.print(solar_volt); lcd.print("V"); lcd.setCursor(14, 0); lcd.write(5); lcd.setCursor(16, 0); lcd.print(temperature); lcd.write(0b11011111); lcd.print("C"); lcd.setCursor(0,1); lcd.write(2); lcd.setCursor(2, 1); lcd.print(bat_volt); lcd.print("V"); lcd.setCursor(14, 1); lcd.write(2); if((charge_status==1) | (charge_status== 2)) { lcd.write(6); } else { lcd.write(7); } lcd.setCursor(0,2); lcd.write(3); lcd.setCursor(2,2); lcd.print(load_current); lcd.print("A"); lcd.setCursor(13,2); lcd.print(watts); lcd.print("W"); lcd.setCursor(0,3); lcd.print("Energy:"); lcd.print(wattHours); lcd.print("WH");      }

Question by Fares Mareai   |  last reply