Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* $Id: UPS_ARDUINO 2009-01-01 22:08:21Z robynhub $ */
- /*
- * Copyright (C) 2008-2009 Antonio Bartolini (robynhub@gmail.com) - Software Design
- * Copyright (C) 2008-2009 Marco Antonini (marcomail.anto@gmail.com) - Hardware Design
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- // Software Version
- #define VERSION "1.14"
- // Enable watchdog (adaboot needed! comment it out otherwise!)
- #define WATCHDOG
- // Enable sounds
- #define SOUNDS
- // Define Hardware version 1.1
- #define HARDWARE_1_1
- #include <Ethernet.h>
- #include <EEPROM.h>
- #include <MsTimer2.h>
- #include <limits.h>
- #ifdef WATCHDOG
- #include <avr/io.h>
- #include <avr/wdt.h>
- #endif
- ////////////////////////////////////// Arduino port listing
- #define UPS_220V_INT 0 /* Interrupt on state of AC line. */
- #define UPS_220V 2 /* State of AC line. LOW if on-line HIGH otherwise */
- #define UPS_DEFAULT_CONFIG 3 /* Read pin for default settings. Always HIGH, with pin goes to LOW */
- #define UPS_LED_ONLINE 4 /* Led 2 "Online" */
- #define UPS_LED_BATTERY 5 /* Led 1 "On Battery" PWM */
- #define UPS_BEEPER 6 /* PWM Beeper */
- #define UPS_BUTTON 7 /* Read Button, always HIGH, LOW if pushed =Used to bypass= */
- #define UPS_DISABLE_CHARGER 8 /* Charger always ON, if HIGH disconnect charger */
- #define UPS_FORCE_TO_BATTERY 9 /* Force to inverter */
- // ANALOG
- #define UPS_ANALOG_VINV 5
- #define UPS_ANALOG_AINV 4
- #define UPS_ANALOG_VBATT 3
- #define UPS_ANALOG_ABATT 2
- /* Sensors Constants: 63.69mV / Volt o 36.60mV / Amp for ver. 1.0
- (analogread()*4.9) / sensors constant(mV) */
- #define CONST_V 63.69
- #define CONST_A 36.60
- /* Ticks between next battery check 360/12 = 30 days */
- #define TICKS_TO_NEXT_BATTERY_CHECK 360
- /* Battery Dead Voltage in Volts */
- #define LOW_BATTERY_VOLTAGE 21
- ////////////////////////////////////// Global Default Config
- byte mac[] = { 0xCA, 0xFE, 0xBA, 0xBE, 0x22, 0x22 };
- byte ip[] = { 192, 168, 1, 1 };
- byte mask[] = { 255 , 255, 255, 0 };
- byte gw[] = { 192 , 168, 1, 1 };
- // telnet defaults to port 4949 (munin client compatible)
- Server server = Server(4949);
- ////////////////////////////////////////////////////////////
- Client client = NULL;
- boolean superuser = false;
- volatile char buffer[64];
- volatile boolean on_battery_check = false;
- volatile unsigned long test_start_time;
- volatile unsigned long test_stop_time;
- volatile int ticks;
- // CONIFIGURATION
- struct config_t {
- // ip
- byte ip[4];
- // mask
- byte mask[4];
- // gw
- byte gw[4];
- // password
- char password[32];
- // days to next battery check (12 ticks = 1 day)
- int ticks;
- // running time on battery
- unsigned long running_time;
- }
- configuration;
- void banner(){
- Serial.println("=== System Started ===");
- Serial.println("Network Config:");
- Serial.print("Ip: ");
- Serial.print((int)configuration.ip[0]);
- Serial.print(".");
- Serial.print((int)configuration.ip[1]);
- Serial.print(".");
- Serial.print((int)configuration.ip[2]);
- Serial.print(".");
- Serial.println((int)configuration.ip[3]);
- Serial.print("Netmask: ");
- Serial.print((int)configuration.mask[0]);
- Serial.print(".");
- Serial.print((int)configuration.mask[1]);
- Serial.print(".");
- Serial.print((int)configuration.mask[2]);
- Serial.print(".");
- Serial.println((int)configuration.mask[3]);
- Serial.print("Gateway: ");
- Serial.print((int)configuration.gw[0]);
- Serial.print(".");
- Serial.print((int)configuration.gw[1]);
- Serial.print(".");
- Serial.print((int)configuration.gw[2]);
- Serial.print(".");
- Serial.println((int)configuration.gw[3]);
- Serial.print("Enable Pass: ");
- Serial.println(configuration.password);
- Serial.print("Running Time: ");
- Serial.println((int)configuration.running_time / 60000 );
- Serial.print("Days to check: ");
- Serial.println(ticks / 12);
- Serial.print("Software Version: ");
- Serial.println(VERSION);
- Serial.println("=== Up and Running ===");
- return;
- }
- // 220V Interrupt Handling
- void interrupt(){
- // quit battery check
- if (digitalRead(UPS_220V) == HIGH && on_battery_check){
- digitalWrite(UPS_FORCE_TO_BATTERY,LOW);
- on_battery_check = false;
- #ifdef HARDWARE_1_1
- pinMode(UPS_DISABLE_CHARGER,INPUT);
- #else
- digitalWrite(UPS_DISABLE_CHARGER, LOW);
- #endif
- }
- init_eth0();
- }
- // Ethernet Initialization
- void init_eth0(){
- Ethernet.begin(mac, configuration.ip, configuration.gw, configuration.mask);
- // start listening for clients
- server.begin();
- }
- void reset(){
- // Watchdog Abuse
- #ifdef WATCHDOG
- while(1) {
- };
- #endif
- }
- // Set values to default
- void apply_default(){
- Serial.println("=== Default Config Applyed ===");
- configuration.ip[0] = ip[0];
- configuration.ip[1] = ip[1];
- configuration.ip[2] = ip[2];
- configuration.ip[3] = ip[3];
- configuration.mask[0] = mask[0];
- configuration.mask[1] = mask[1];
- configuration.mask[2] = mask[2];
- configuration.mask[3] = mask[3];
- configuration.gw[0] = gw[0];
- configuration.gw[1] = gw[1];
- configuration.gw[2] = gw[2];
- configuration.gw[3] = gw[3];
- strcpy(configuration.password,"arduino");
- configuration.ticks = TICKS_TO_NEXT_BATTERY_CHECK;
- configuration.running_time = 0;
- save_config();
- #ifdef SOUNDS
- // bip bip bip!
- tone(UPS_BEEPER,2048,500);
- delay(500);
- tone(UPS_BEEPER,2048,500);
- delay(500);
- tone(UPS_BEEPER,2048,500);
- delay(500);
- noTone(UPS_BEEPER);
- #endif
- return;
- }
- // Bypass button handling
- void bypass_button(){
- // do nothing if on battery
- if (on_battery_check || digitalRead(UPS_220V) == HIGH)
- return;
- // Bypass
- if (digitalRead(UPS_BUTTON) == LOW)
- force_to_battery(HIGH);
- else
- force_to_battery(LOW);
- }
- // Return true if the load it's on battery
- boolean on_battery(){
- if (digitalRead(UPS_220V) == HIGH)
- return true;
- else if (on_battery_check)
- return true;
- else if (digitalRead(UPS_BUTTON) == LOW)
- return true;
- else
- return false;
- }
- // Force the load to go on battery
- void force_to_battery(int value){
- // avoid problems
- if (digitalRead(UPS_220V) == HIGH && value == HIGH)
- return;
- if (digitalRead(UPS_220V) == LOW)
- digitalWrite(UPS_FORCE_TO_BATTERY,value);
- else
- // UPS_220 == HIGH
- digitalWrite(UPS_FORCE_TO_BATTERY,LOW);
- }
- // battery check timer
- void battery_check_timer(){
- // reinit eth0
- init_eth0();
- if (!on_battery_check){
- ticks--;
- if (ticks <= 0){
- battery_check_start();
- }
- }
- }
- // start battery check
- void battery_check_start(){
- on_battery_check = true;
- test_start_time = millis();
- force_to_battery(HIGH);
- #ifdef HARDWARE_1_1
- pinMode(UPS_DISABLE_CHARGER,OUTPUT);
- digitalWrite(UPS_DISABLE_CHARGER, LOW);
- #else
- digitalWrite(UPS_DISABLE_CHARGER, HIGH);
- #endif
- }
- // stop battery check
- void battery_check_stop(){
- #ifdef HARDWARE_1_1
- pinMode(UPS_DISABLE_CHARGER,INPUT);
- #else
- digitalWrite(UPS_DISABLE_CHARGER, LOW);
- #endif
- force_to_battery(LOW);
- test_stop_time = millis();
- if (test_start_time > test_stop_time)
- configuration.running_time = (test_stop_time + (ULONG_MAX - test_start_time));
- else
- configuration.running_time = test_stop_time - test_start_time;
- // Reset Ticks
- ticks = TICKS_TO_NEXT_BATTERY_CHECK;
- save_config();
- on_battery_check = false;
- init_eth0();
- }
- // Write a struct in eeprom
- template <class T> int EEPROM_writeAnything(int ee, const T& value)
- {
- const byte* p = (const byte*)(const void*)&value;
- int i;
- for (i = 0; i < sizeof(value); i++)
- EEPROM.write(ee++, *p++);
- return i;
- }
- // Read a struct in eeprom
- template <class T> int EEPROM_readAnything(int ee, T& value)
- {
- byte* p = (byte*)(void*)&value;
- int i;
- for (i = 0; i < sizeof(value); i++)
- *p++ = EEPROM.read(ee++);
- return i;
- }
- // Routine to save config
- void save_config(){
- configuration.ticks = ticks;
- EEPROM_writeAnything(0, configuration);
- return;
- }
- // Sensors values convertion
- float convert(int value, float constant){
- return ((value * 4.9)/constant);
- }
- // Return the voltage of the inverter in Volts
- float read_inverter_voltage(){
- #ifdef HARDWARE_1_1
- return convert(analogRead(UPS_ANALOG_VBATT), CONST_V);
- #else
- return convert(analogRead(UPS_ANALOG_VINV), CONST_V);
- #endif
- }
- // Return the current of the inverter in Ampere
- float read_inverter_ampere(){
- return convert(analogRead(UPS_ANALOG_AINV), CONST_A);
- }
- // Return the voltage of the batteries in Volts
- float read_battery_voltage(){
- return convert(analogRead(UPS_ANALOG_VBATT), CONST_V);
- }
- // Return the current of the batteries in Ampere
- float read_battery_ampere(){
- return convert(analogRead(UPS_ANALOG_ABATT), CONST_A);
- }
- int check_login(volatile char * buffer) {
- // superuser login
- if (buffer[0] == 'e' &&
- buffer[1] == 'n' &&
- buffer[2] == 'a' &&
- buffer[3] == 'b' &&
- buffer[4] == 'l' &&
- buffer[5] == 'e'){
- for (int i = 0 ; i < 16 ; i++ ){
- if (buffer[i+7] == 13 && configuration.password[i] == 0){
- server.println("# Login OK");
- server.print("$ ");
- superuser = true;
- return 1;
- }
- // check password
- if (buffer[i+7] != configuration.password[i])
- break;
- }
- server.println("# Wrong login");
- superuser = false;
- return 0;
- }
- return 2;
- }
- void parse_command(volatile char * buffer){
- // test
- if (buffer[0] == 't' &&
- buffer[1] == 'e' &&
- buffer[2] == 's' &&
- buffer[3] == 't'){
- if (superuser){
- battery_check_start();
- server.println("# Battery Test Started");
- }
- else not_allowed();
- }
- // setpass
- else if (buffer[0] == 's' &&
- buffer[1] == 'e' &&
- buffer[2] == 't' &&
- buffer[3] == 'p' &&
- buffer[4] == 'a' &&
- buffer[5] == 's' &&
- buffer[6] == 's' &&
- buffer[7] == ' '){
- if (superuser){
- int i = 8;
- for ( ; i< 31 ; i++){
- if (buffer[i] == 13){
- configuration.password[i-8] = 0;
- break;
- }
- else
- configuration.password[i-8] = buffer[i];
- }
- server.print("# Saved password: ");
- server.println(configuration.password);
- save_config();
- }
- else not_allowed();
- }
- // fetch data
- else if (buffer[0] == 'f' &&
- buffer[1] == 'e' &&
- buffer[2] == 't' &&
- buffer[3] == 'c' &&
- buffer[4] == 'h' &&
- buffer[5] == ' ' &&
- buffer[6] == 'd' &&
- buffer[7] == 'a' &&
- buffer[8] == 't' &&
- buffer[9] == 'a'){
- server.print("running_time.value ");
- server.print(configuration.running_time / 60000);
- server.print("\nnextcheck.value ");
- server.print(ticks / 12);
- server.print("\nonline.value ");
- server.print(digitalRead(UPS_220V) == LOW);
- server.print("\nbatt_v.value ");
- server.print((int)(read_battery_voltage() * 100));
- server.print("\nbatt_a.value ");
- server.print((int)(read_battery_ampere() * 100));
- server.print("\ninv_v.value ");
- server.print((int)(read_inverter_voltage() * 100));
- server.print("\ninv_a.value ");
- server.print((int)(read_inverter_ampere() * 100));
- if (superuser){
- #ifdef HARDWARE_1_1
- server.print("\nhardwareversion.value 1.1");
- #else
- server.print("\nhardwareversion.value 1.0");
- #endif
- server.print("\nsoftwareversion.value ");
- server.print(VERSION);
- server.print("\non_battery_check.value ");
- server.print(on_battery_check == true);
- server.print("\non_battery.value ");
- server.print(on_battery() == true);
- }
- server.print("\n.\n");
- }
- // save
- else if (buffer[0] == 's' &&
- buffer[1] == 'a' &&
- buffer[2] == 'v' &&
- buffer[3] == 'e'){
- if (superuser){
- save_config();
- server.println("# Configuration saved");
- }
- else not_allowed();
- }
- // disable
- else if (buffer[0] == 'd' &&
- buffer[1] == 'i' &&
- buffer[2] == 's' &&
- buffer[3] == 'a' &&
- buffer[4] == 'b' &&
- buffer[5] == 'l' &&
- buffer[6] == 'e' ){
- superuser=false;
- server.println("# Disable OK");
- }
- // ipapply
- else if (buffer[0] == 'i' &&
- buffer[1] == 'p' &&
- buffer[2] == 'a' &&
- buffer[3] == 'p' &&
- buffer[4] == 'p' &&
- buffer[5] == 'l' &&
- buffer[6] == 'y'){
- if (superuser){
- server.println("# Apply new IP setting.");
- server.println("# Please connect to the new ip address.");
- client.stop();
- save_config();
- init_eth0();
- }
- else not_allowed();
- }
- // quit || exit
- else if ((buffer[0] == 'q' &&
- buffer[1] == 'u' &&
- buffer[2] == 'i' &&
- buffer[3] == 't') ||
- (
- buffer[0] == 'e' &&
- buffer[1] == 'x' &&
- buffer[2] == 'i' &&
- buffer[3] == 't')){
- superuser = false;
- client.stop();
- }
- else if (buffer[0] == 'r' &&
- buffer[1] == 'e' &&
- buffer[2] == 'b' &&
- buffer[3] == 'o' &&
- buffer[4] == 'o' &&
- buffer[5] == 't'){
- if (superuser){
- server.println("# Rebooting");
- superuser = false;
- client.stop();
- reset();
- }
- }
- //ipconfigs
- else if (buffer[0] == 'i' &&
- buffer[1] == 'p' &&
- buffer[2] == 'c' &&
- buffer[3] == 'o' &&
- buffer[4] == 'n' &&
- buffer[5] == 'f' &&
- buffer[6] == 'i' &&
- buffer[7] == 'g'){
- if (superuser){
- server.println("# Network Config:");
- server.print("# Ip: ");
- server.print((int)configuration.ip[0]);
- server.print(".");
- server.print((int)configuration.ip[1]);
- server.print(".");
- server.print((int)configuration.ip[2]);
- server.print(".");
- server.println((int)configuration.ip[3]);
- server.print("# Netmask: ");
- server.print((int)configuration.mask[0]);
- server.print(".");
- server.print((int)configuration.mask[1]);
- server.print(".");
- server.print((int)configuration.mask[2]);
- server.print(".");
- server.println((int)configuration.mask[3]);
- server.print("# Gateway: ");
- server.print((int)configuration.gw[0]);
- server.print(".");
- server.print((int)configuration.gw[1]);
- server.print(".");
- server.print((int)configuration.gw[2]);
- server.print(".");
- server.println((int)configuration.gw[3]);
- }
- else not_allowed();
- }
- //ip
- else if (buffer[0] == 'i' &&
- buffer[1] == 'p' ){
- if (superuser){
- int base = 3;
- int ott[4];
- for (int i = 0 ; i < 4 ; i++){
- ott[i] = (atoi((char*)&buffer[base]));
- if (ott[i] > 255){
- server.println("# Wrong Format (size)");
- return;
- }
- if (i < 3) {
- if (buffer[base + 1] == '.') base = base + 2;
- else if (buffer[base + 2] == '.') base = base + 3;
- else if (buffer[base + 3] == '.') base = base + 4;
- else {
- server.println("# Wrong Format (dots)");
- return;
- }
- }
- }
- // apply
- for (int i = 0 ; i < 4 ; i++)
- configuration.ip[i] = (byte)ott[i];
- server.println("# Ip Address Set");
- }
- else not_allowed();
- }
- //mask
- else if (buffer[0] == 'm' &&
- buffer[1] == 'a' &&
- buffer[2] == 's' &&
- buffer[3] == 'k'){
- if (superuser){
- int base = 5;
- int ott[4];
- for (int i = 0 ; i < 4 ; i++){
- ott[i] = (atoi((char*)&buffer[base]));
- if (ott[i] > 255){
- server.println("# Wrong Format (size)");
- return;
- }
- if (i < 3) {
- if (buffer[base + 1] == '.') base = base + 2;
- else if (buffer[base + 2] == '.') base = base + 3;
- else if (buffer[base + 3] == '.') base = base + 4;
- else {
- server.println("# Wrong Format (dots)");
- return;
- }
- }
- }
- // apply
- for (int i = 0 ; i < 4 ; i++)
- configuration.mask[i] = (byte)ott[i];
- server.println("# Network Mask Set");
- }
- else not_allowed();
- }
- //gw
- else if (buffer[0] == 'g' &&
- buffer[1] == 'w' ){
- if (superuser){
- int base = 3;
- int ott[4];
- for (int i = 0 ; i < 4 ; i++){
- ott[i] = (atoi((char*)&buffer[base]));
- if (ott[i] > 255){
- server.println("# Wrong Format (size)");
- return;
- }
- if (i < 3) {
- if (buffer[base + 1] == '.') base = base + 2;
- else if (buffer[base + 2] == '.') base = base + 3;
- else if (buffer[base + 3] == '.') base = base + 4;
- else {
- server.println("# Wrong Format (dots)");
- return;
- }
- }
- }
- // apply
- for (int i = 0 ; i < 4 ; i++)
- configuration.gw[i] = (byte)ott[i];
- server.println("# Network Gateway Set");
- }
- else not_allowed();
- }
- //help
- else if (buffer[0] == 'h' &&
- buffer[1] == 'e' &&
- buffer[2] == 'l' &&
- buffer[3] == 'p'){
- server.println("# Available Commands are: ");
- server.println("fetch data,\nenable [PASS],\nsetpass [PASS],\ndisable,\nsave,\ntest,\nipconfig,\nipapply,\nip [ADDR],\nmask [NMASK],\ngw [ADDR],\nquit,\nreboot,\nexit");
- }
- else server.println("# Unknown Command");
- }
- void not_allowed(){
- server.println("# Not Allowed");
- }
- void setup()
- {
- #ifdef WATCHDOG
- wdt_enable(WDTO_2S);
- #endif
- pinMode(UPS_DEFAULT_CONFIG, INPUT);
- pinMode(UPS_220V, INPUT);
- pinMode(UPS_BUTTON, INPUT);
- #ifdef HARDWARE_1_1
- pinMode(UPS_DISABLE_CHARGER,INPUT);
- #else
- pinMode(UPS_DISABLE_CHARGER, OUTPUT);
- // sanity check
- digitalWrite(UPS_DISABLE_CHARGER, LOW);
- #endif
- pinMode(UPS_FORCE_TO_BATTERY, OUTPUT);
- pinMode(UPS_LED_ONLINE, OUTPUT);
- pinMode(UPS_LED_BATTERY, OUTPUT);
- pinMode(UPS_BEEPER, OUTPUT);
- on_battery_check = false;
- force_to_battery(LOW);
- // Force Defaults
- if (digitalRead(UPS_DEFAULT_CONFIG) == LOW)
- apply_default();
- // Read the config
- EEPROM_readAnything(0, configuration);
- ticks = configuration.ticks;
- // INTERRUPT
- attachInterrupt(UPS_220V_INT, interrupt , CHANGE);
- // Set timer for self-check
- MsTimer2::set(7200000, battery_check_timer);
- // 900.000ms period (15 min)
- // 3.600.000ms period (1h)
- // 86.400.000ms period (24h)
- MsTimer2::start();
- init_eth0();
- // tiny debug on serial
- Serial.begin(9600);
- banner();
- }
- void loop()
- {
- #ifdef WATCHDOG
- wdt_reset();
- #endif
- if (on_battery()){
- digitalWrite(UPS_LED_BATTERY,HIGH);
- digitalWrite(UPS_LED_ONLINE,LOW);
- if (! on_battery_check){
- // beep
- #ifdef SOUNDS
- tone(UPS_BEEPER,2048);
- #endif
- }
- else // we're on battery check
- if(read_battery_voltage() < LOW_BATTERY_VOLTAGE) // check battery Status and stop if under limit
- battery_check_stop();
- }
- else {
- // we're on line!
- digitalWrite(UPS_LED_BATTERY,LOW);
- digitalWrite(UPS_LED_ONLINE,HIGH);
- #ifdef SOUNDS
- // shut up beep!
- noTone(UPS_BEEPER);
- #endif
- }
- bypass_button();
- // wait for a new connection
- client = server.available();
- // new client connected
- if (client) {
- int i=0;
- // connection estabiished
- while (client.connected()) {
- #ifdef WATCHDOG
- wdt_reset();
- #endif
- // there is some data available
- if (client.available()) {
- // check request length
- if (i >= 63) break;
- // read a char
- buffer[i] = client.read();
- // check if is the termination of the string
- if (buffer[i] == '\n'){
- if(check_login(buffer) < 2)
- break;
- else
- parse_command(buffer);
- if (superuser)
- server.print("$ ");
- break;
- }
- i++;
- } // end if available
- } // end while connected
- } // end if client
- } // end loop
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement