commit adb0fe2037d876095f65c6da67da8b105e11d495 Author: Nigreon Date: Tue Dec 30 22:38:10 2025 +0100 First commit diff --git a/fuses.orig b/fuses.orig new file mode 100644 index 0000000..e9694fa --- /dev/null +++ b/fuses.orig @@ -0,0 +1,12 @@ +junk: :09000000 +fuse0: 00 +fuse1: 00 +fuse2: 02 +fuse3: FF +fuse4: 00 +fuse5: F6 +fuse6: 07 +fuse7: 00 +fuse8: 00 +junk: F9 +more junk: :00000001FF diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..5f342ab --- /dev/null +++ b/platformio.ini @@ -0,0 +1,24 @@ +[platformio] +default_envs = tiny1614 + +[env:tiny1614] +platform = atmelmegaavr +platform_packages = framework-arduino-megaavr-megatinycore @ https://github.com/SpenceKonde/megaTinyCore/ +board = ATtiny1614 +framework = arduino +board_build.f_cpu = 4000000L +board_hardware.bod = disabled +lib_deps = + robtillaart/SHT4x +upload_protocol = serialupdi +#upload_flags = +# -P$UPLOAD_PORT +# -b$UPLOAD_SPEED +# -V +targets = upload, monitor +#targets = upload +#upload_speed = 19200 +monitor_filters = time +upload_port = /dev/ttyACM0 +monitor_speed = 9600 +monitor_port = /dev/ttyUSB0 diff --git a/src/inFactoryTransmit.h b/src/inFactoryTransmit.h new file mode 100644 index 0000000..8360e89 --- /dev/null +++ b/src/inFactoryTransmit.h @@ -0,0 +1 @@ +void sendInfactory(int pin, uint8_t id, uint8_t channel, bool batteryOK, bool button, uint8_t humidity, float temperature); diff --git a/src/inFactoryTransmit.ino b/src/inFactoryTransmit.ino new file mode 100644 index 0000000..c1a4cc0 --- /dev/null +++ b/src/inFactoryTransmit.ino @@ -0,0 +1,97 @@ +uint8_t msg[5]; +uint8_t pin_tx; + +uint8_t crc4(uint8_t const message[], unsigned nBytes, uint8_t polynomial, uint8_t init) +{ + unsigned remainder = init << 4; // LSBs are unused + unsigned poly = polynomial << 4; + unsigned bit; + + while (nBytes--) { + remainder ^= *message++; + for (bit = 0; bit < 8; bit++) { + if (remainder & 0x80) { + remainder = (remainder << 1) ^ poly; + } else { + remainder = (remainder << 1); + } + } + } + return remainder >> 4 & 0x0f; // discard the LSBs +} + +void sendInfactory(int pin, uint8_t id, uint8_t channel, bool batteryOK, bool button, uint8_t humidity, float temperature) { + pin_tx = pin; + // put your setup code here, to run once: + msg[0] = id; + msg[4] = channel + ((humidity%10) << 4 ); + msg[3] = humidity/10; + + //int binTemp = ((temperature * 9./5) + 32 + 90)*10; + int binTemp = (temperature+90)*10; + msg[3] += (binTemp & 0x0F) << 4; + msg[2] = binTemp >> 4; + + //msg[1] = batteryOK << 2; + msg[1] = button << 3; + msg[1] = msg[1] | (!batteryOK << 2); + + msg[1] = (msg[1] & 0x0F) | (msg[4] & 0x0F) << 4; + // crc4() only works with full bytes + uint8_t crc = crc4(msg, 4, 0x13, 0); // Koopmann 0x9, CCITT-4; FP-4; ITU-T G.704 + crc ^= msg[4] >> 4; // last nibble is only XORed + + msg[1] = (msg[1] & 0x0F) | (crc & 0x0F) << 4; + + //for (int i=0; i<=4; i++){ + // Serial.print(msg[i],HEX); + // Serial.print(" "); + //} + + sendRF(); +} + +void sendRF() +{ +/*low long 4000 +low short 1800 +high short 700 +*/ + + noInterrupts(); + //for (int n=0; n<6; n++) + for (int n=0; n<2; n++) + { + for (int i=0; i<8; i++){ + digitalWrite(pin_tx, !(i%2)); + delayMicroseconds(1000); + } + digitalWrite(pin_tx, HIGH); + delayMicroseconds(550); + digitalWrite(pin_tx, LOW); + delayMicroseconds(8000); + + for (int i = 0; i<5; i++) { + for (int b = 7; b>=0; b--) { + digitalWrite(pin_tx, HIGH); + //delayMicroseconds(700); + delayMicroseconds(550); + digitalWrite(pin_tx, LOW); + if (bitRead(msg[i], b)){ + delayMicroseconds(4000); + } + else{ + //delayMicroseconds(1800); + delayMicroseconds(2000); + } + } + } + + digitalWrite(pin_tx, HIGH); + delayMicroseconds(550); + digitalWrite(pin_tx, LOW); + + delayMicroseconds(16000); + } + interrupts(); +} diff --git a/src/main.ino b/src/main.ino new file mode 100644 index 0000000..62f59b3 --- /dev/null +++ b/src/main.ino @@ -0,0 +1,155 @@ +#include +#include "Wire.h" +#include "SHT4x.h" + +#include "inFactoryTransmit.h" + +#define PIN_TX 3 +#define CHANNEL 1 +#define ID 11 + +SHT4x sht; + +bool butval = false; +bool batval = true; +int8_t sendfromstart = 0; +int8_t sendcountbat = 0; + +void RTC_init(void) +{ + /* Initialize RTC: */ + while (RTC.STATUS > 0) + { + ; /* Wait for all register to be synchronized */ + } + RTC.CLKSEL = RTC_CLKSEL_INT32K_gc; /* 32.768kHz Internal Ultra-Low-Power Oscillator (OSCULP32K) */ + + RTC.PITINTCTRL = RTC_PI_bm; /* PIT Interrupt: enabled */ + + RTC.PITCTRLA = RTC_PERIOD_CYC16384_gc /* RTC Clock Cycles 16384, resulting in 32.768kHz/16384 = 2Hz */ + | RTC_PITEN_bm; /* Enable PIT counter: enabled */ +} + +ISR(RTC_PIT_vect) +{ + RTC.PITINTFLAGS = RTC_PI_bm; /* Clear interrupt flag by writing '1' (required) */ +} + +void sleepNSeconds(uint16_t val) { + // Serial.flush(); + // first cycle may not be full cycle + //disableAllPeripherals(); // all off + for (uint16_t i = 0; i < (val*2) ; i++) { + //diagnosticPinLow(); // set low to show sleeping + sleep_cpu(); // put MCU to sleep + //diagnosticPinHigh(); // set high to show awake + } + // now awake, sleep cycles complete, continue on + //initSerialGPIO(); // initialize serial and GPIO +} + + +//returns Vdd volts*100 (3.21v = return 321) +uint16_t readVdd() { + uint16_t ret; + //ADC0.CTRLA |= ADC_ENABLE_bm; + //adc0 VREF = 1v1 + VREF.CTRLA = (VREF.CTRLA & ~VREF_ADC0REFSEL_gm) | VREF_ADC0REFSEL_1V1_gc; + ADC0.CTRLB = ADC_SAMPNUM_ACC64_gc; //64 samples + ADC0.CTRLC = ADC_REFSEL_VDDREF_gc | ADC_PRESC_DIV16_gc | ADC_SAMPCAP_bm; + ADC0.CTRLD = ADC_INITDLY_DLY64_gc; + ADC0.MUXPOS = ADC_MUXPOS_INTREF_gc; + ADC0.CTRLA = 1; //enable adc + ADC0.COMMAND = 1; //start + while( ADC0.COMMAND ){} //wait + //Vdd*100 = 1023*1.1*100*64/res (64 samples, so *64 also) + + ret = (1023*1.1*100ul*64) / ADC0.RES; + + ADC0.CTRLA &= ~ADC_ENABLE_bm; + + //Serial.print("Vdd: "); + //Serial.println(ret); + + return ret; +} + +bool batok() { + return (readVdd()-240)/0.4 < 20 ? false : true; +} + +void setup(void) +{ + RTC_init(); /* Initialize the RTC timer */ + set_sleep_mode(SLEEP_MODE_PWR_DOWN); /* Set sleep mode to POWER DOWN mode */ + sleep_enable(); /* Enable sleep mode, but not going to sleep yet */ + ADC0.CTRLA &= ~ADC_ENABLE_bm; // Disable ADC + TCA0.SPLIT.CTRLA = 0; // Disable Timers + pinMode(PIN_PA0, INPUT_PULLUP); + pinMode(PIN_PA1, INPUT_PULLUP); + pinMode(PIN_PA2, INPUT_PULLUP); + pinMode(PIN_PA3, INPUT_PULLUP); + pinMode(PIN_PA4, INPUT_PULLUP); + pinMode(PIN_PA5, INPUT_PULLUP); + pinMode(PIN_PA6, INPUT_PULLUP); + + USART0.CTRLB &= ~USART_RXEN_bm & ~USART_TXEN_bm; // disable USART + pinMode(PIN_PB2, INPUT_PULLUP); + pinMode(PIN_PB3, INPUT_PULLUP); + + //Serial.begin(9600); + //Serial.println("Hello ATTiny1614"); + + pinMode(PIN_TX, OUTPUT); + + batval = batok(); + + Wire.begin(); + sht.begin(); + sht.setHeatProtection(false); + sht.read(); +} + +void loop(void) +{ + //readVdd(); + if(sht.read() == true) { + float temperature = sht.getFahrenheit(); + //float temperature = sht.getTemperature(); + uint8_t humidity = (uint8_t) sht.getHumidity(); + //Serial.print("Temperature "); + //Serial.println(sht.getTemperature(), 1); + //Serial.print("Humidity "); + //Serial.println(humidity, 1); + if(sendfromstart == 10) + { + butval = false; + sendfromstart = -1; + sendcountbat = 0; + } else if(sendfromstart >= 0) + { + butval = true; + sendfromstart++; + } + if(sendcountbat == 2) + //if(sendcountbat == 60) + { + sendcountbat = 0; + batval = batok(); + } else { + sendcountbat++; + } + sendInfactory(PIN_TX, ID, CHANNEL, batval, butval, humidity, temperature); + } else { + //Serial.print("SHT Error "); + //Serial.println(sht.getError()); + } + if(butval == true) { + //Serial.println("Sleep Short"); + sleepNSeconds(25+random(0,10)); + } else { + //Serial.println("Sleep Long"); + sleepNSeconds(55+random(0,10)); + } + //delay(5000); +}