sketch_ups_nano_1.ino
#include <EEPROM.h>
#include <CRC32.h>
#include <OneWire.h> 
#include <DallasTemperature.h>
 
#define pinInpT        2
#define pinInpACOK     3
#define pinInpBatLow   4
#define pinInpAux      5
#define pinOutLedBat   6
#define pinOutLedPlc   7
#define pinOutBeep     8
#define pinOutBatCtrl  9
#define pinOutCooler   10
#define pinOutAux      11
#define pinOutLedRun   LED_BUILTIN
 
#define VERSION            0
#define REQUEST_LEN        15
#define REQUEST_TIMEOUT    100
#define DEFAULT_TIMEOUT_SERIAL  10
#define DEFAULT_TIMEOUT_BATCTRL  5
 
#define ADDR_SERIAL_CONNECTED   0
#define ADDR_BAT_CTRL           2
#define ADDR_T_OFF              4
#define ADDR_T_ON               6
#define ADDR_BEEP_MODE          8
 
OneWire oneWire(pinInpT); 
DallasTemperature dallasTemp(&oneWire);
 
 
int     T;
int     Toff;
int     Ton;
 
boolean outBeep;
boolean outBatCtrl;
boolean outCooler;
boolean outAux;
boolean outLedBat;
boolean outLedPlc;
 
boolean manual_BatCtrl;
boolean manual_Cooler;
int beep_mode;
 
int timeBatCtrl;
int cntBatCtrl;
 
int cntLedPlc;
 
long ms;
int cnt5000ms;
int cnt1000ms;
int cnt200ms;
 
boolean serConnected;
int timeoutSerialConnected;
long serms;
int  sercnt;
uint8_t  serbuf[REQUEST_LEN];
 
boolean auxIfNotConnected;
 
void setup() {
  pinMode(pinInpACOK, INPUT);
  pinMode(pinInpBatLow, INPUT);
  pinMode(pinInpAux, INPUT);
  pinMode(pinOutLedBat, OUTPUT);
  pinMode(pinOutLedPlc, OUTPUT);
  pinMode(pinOutBeep, OUTPUT);
  pinMode(pinOutBatCtrl, OUTPUT);
  pinMode(pinOutCooler, OUTPUT);
  pinMode(pinOutAux, OUTPUT);
  pinMode(pinOutLedRun, OUTPUT);
 
  Serial.begin(9600); 
 
  dallasTemp.begin();
  dallasTemp.setWaitForConversion(false);
  dallasTemp.requestTemperatures();
 
  manual_BatCtrl = false;
  manual_Cooler = false;
  cnt5000ms = 0;
  cnt1000ms = 0;
  cnt200ms = 0;
  cntLedPlc = 0;
  cntBatCtrl = 0;
  auxIfNotConnected = false;
  sercnt = 0;
  serConnected = false;
  ms = millis(); 
 
  EEPROM.get(ADDR_SERIAL_CONNECTED, timeoutSerialConnected);
  EEPROM.get(ADDR_BAT_CTRL, timeBatCtrl);
  EEPROM.get(ADDR_T_OFF, Toff);
  EEPROM.get(ADDR_T_ON, Ton);
  EEPROM.get(ADDR_BEEP_MODE, beep_mode);
 
  validate_vars();
  greeting();
}
 
 
 
void greeting() {
  Serial.print("UPS NANO version ");
  Serial.println(VERSION);
 
  Serial.print("SerTimeout = ");
  Serial.println(timeoutSerialConnected);
  Serial.print("BatCtrlTimeout = ");
  Serial.println(timeBatCtrl);
  Serial.print("Toff = ");
  Serial.println(Toff);
  Serial.print("Ton = ");
  Serial.println(Ton);
}
 
 
 
void validate_vars() {
  if(timeBatCtrl <= 0)
    timeBatCtrl = 1;
 
  if(timeoutSerialConnected <= 0)
    timeoutSerialConnected = 1;
 
  if(beep_mode < 0  ||  beep_mode > 2)
    beep_mode = 0;
}
 
 
 
void loop() {
  long msdelta = millis() - ms;
  if( msdelta >= 100 ) {
    ms += 100;
    loop100ms();
  } else 
  if( msdelta < 0 )  {
    msdelta += 0x80000000L;
    if( msdelta >= 100 ) {
      ms += 100 + 0x80000000L;
      loop100ms();
    }
  }
 
  if( Serial ) {
    if( Serial.available() == 0 ) {
      msdelta = millis() - serms;
      if( msdelta < 0 )  
        msdelta += 0x80000000L;
      if( sercnt > 0  &&  msdelta > REQUEST_TIMEOUT ) {
        sercnt = 0;
        serConnected = false;
      }
      if( serConnected  &&  (msdelta/1000) >= timeoutSerialConnected ) {
        serConnected = false;
      }
    } else {
      while( Serial.available() > 0 ) {
        serbuf[sercnt++] = Serial.read();
        if( sercnt == REQUEST_LEN ) {
          onSerRequest();
          sercnt = 0;
//          serConnected = true;
        }
      }
      serms = millis();  
    }
  }
}
 
 
 
void loop100ms() {
  if( cnt5000ms++ >= 50 ) { 
    cnt5000ms = 0;
    loop5000ms();
  }
 
  if( cnt1000ms++ >= 10 ) { 
    cnt1000ms = 0;
    loop1000ms();
  }
 
  if( cnt200ms++ >= 2 ) { 
    cnt200ms = 0;
    loop200ms();
  }
 
  // led plc
  if( !serConnected ) {
    if( cntLedPlc++ < 10 )
      outLedPlc = cntLedPlc % 2;
    else if( cntLedPlc >= 30 ) {
      outLedPlc = false;
      cntLedPlc = 0;
    }
  } else 
    cntLedPlc = 0;
 
  digitalWrite(pinOutLedPlc, !outLedPlc); //inv
  digitalWrite(pinOutLedRun, !outLedPlc); //inv
  digitalWrite(pinOutLedBat, !outLedBat); //inv
}
 
 
 
void loop200ms() {
  // led bat
  if( digitalRead(pinInpACOK) ) { //inv
    if( (!digitalRead(pinInpBatLow)) == HIGH ) //inv
      outLedBat = !outLedBat;
    else  
      outLedBat = HIGH;
  } else
    outLedBat = LOW;
}
 
 
 
void loop1000ms() {
  if( serConnected )
    outLedPlc = !outLedPlc;
 
  // bat control
  if( !manual_BatCtrl ) {
    outBatCtrl = 1;
    if( timeBatCtrl > 0  &&  !serConnected ) {
      if( digitalRead(pinInpACOK) ) { //inv
        if( cntBatCtrl >= timeBatCtrl ) {
          outBatCtrl = 0;
        } else
          cntBatCtrl++;
      } else
        cntBatCtrl = 0;
    }
  }
  digitalWrite(pinOutBatCtrl, outBatCtrl); //
 
  // beep
  if( digitalRead(pinInpACOK) ) { //inv
    if( outBeep = !outBeep )
      // second arg:
      //   1200 - normal tone
      //     40 - debug tone (very low)
      if( beep_mode == 0 )
        tone(pinOutBeep, 1200, 1000); 
      else if( beep_mode == 1 )
        tone(pinOutBeep, 40, 1000); 
    else
      noTone(pinOutBeep);  
  } 
 
  // aux
  if(auxIfNotConnected) 
    outAux = !serConnected;
  digitalWrite(pinOutAux, !outAux); //inv
 
  // cooler
  int t = (int)round(dallasTemp.getTempCByIndex(0) * 10);
  dallasTemp.requestTemperatures();
  if( t > -500  &&  t < 1200 )
    T = t;
 
  if( !manual_Cooler ) {
    if( Ton > Toff? T >= Ton: T <= Ton )
      outCooler = 1;
    else
    if( Ton > Toff? T <= Toff: T >= Toff )
      outCooler = 0;
  }
  digitalWrite(pinOutCooler, !outCooler); //inv
}
 
 
 
void loop5000ms() {
}
 
 
void onSerRequest() {
  serConnected = false;
 
  uint32_t cs1 = CRC32::calculate(serbuf, REQUEST_LEN-4);
  uint32_t cs2 = 
        (((uint32_t)serbuf[REQUEST_LEN-4])<<24) + 
        (((uint32_t)serbuf[REQUEST_LEN-3])<<16) + 
        (((uint32_t)serbuf[REQUEST_LEN-2])<<8) + 
          (uint32_t)serbuf[REQUEST_LEN-1];
 
  if( cs1 != cs2 ) {
    return;
  }
 
  if( serbuf[0] != VERSION ) {
    sendErrorVersion();
    return;
  }
 
  getSerbufValues();
  sendGoodAnswer();
 
  serConnected = true;
}
 
 
 
void sendGoodAnswer() {
  serbuf[0] = 0;
  serbuf[1] = (!digitalRead(pinInpACOK)) + (!digitalRead(pinInpBatLow))*2 + (!digitalRead(pinInpAux))*4;
  serbuf[2] = (T >> 8) & 0xFF;
  serbuf[3] = T & 0xFF;
 
  addSerbufCrc(4);
  Serial.write(serbuf, 8);
}
 
 
 
void sendErrorVersion() {
    serbuf[0] = 0xFF;
    serbuf[1] = VERSION;
    serbuf[2] = serbuf[3] = 0;
    addSerbufCrc(4);
    Serial.write(serbuf, 8);
}
 
 
 
void addSerbufCrc(int len) {
  uint32_t cs = CRC32::calculate(serbuf, len);
  serbuf[len++] = cs >> 24;
  serbuf[len++] = (cs %= 0x1000000) >> 16;
  serbuf[len++] = (cs %= 0x10000) >> 8;
  serbuf[len++] = cs %= 0x100;
}
 
 
 
void getSerbufValues() {
  timeBatCtrl = 
        (serbuf[1] << 8) + 
         serbuf[2];
 
  timeoutSerialConnected = 
        (serbuf[3] << 8) + 
         serbuf[4];
 
  Ton = 
        (serbuf[5] << 8) + 
         serbuf[6];
 
  Toff = 
        (serbuf[7] << 8) + 
         serbuf[8];
 
  int aux_mode = 
         serbuf[9] & 3;
 
  if( aux_mode == 0 )
    outAux = 0;
  else if( aux_mode == 1 )
    outAux = 1;
  auxIfNotConnected = (aux_mode == 2);
 
  int manuals = 
        serbuf[10];
 
  manual_BatCtrl = (manuals & 0x1) > 0;
  if( manual_BatCtrl )
    outBatCtrl = (manuals & 0x2) > 0;
 
  manual_Cooler = (manuals & 0x4) > 0;
  if( manual_Cooler )
    outCooler = (manuals & 0x8) > 0;
 
  beep_mode = (manuals >> 4) & 0xF;
 
  validate_vars();
 
  EEPROM.put(ADDR_SERIAL_CONNECTED, timeoutSerialConnected);
  EEPROM.put(ADDR_BAT_CTRL, timeBatCtrl);
  EEPROM.put(ADDR_T_OFF, Toff);
  EEPROM.put(ADDR_T_ON, Ton);
  EEPROM.put(ADDR_BEEP_MODE, beep_mode);
}
 
 
 
doc/jroboplc/ups_devices/ups_nano_src.txt · Последние изменения: 2018/07/27 13:21 — denis
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0