Hi,
different project now, but again Manchester code hassles with an ATtiny85. I am using the ATtiny85 to read some sensor values (BME280 pressure/humidity/temperature and GY-30 light intensity, both via I²C) plus battery level and send it about every minute to an ESP32.
Since there is no compatible Manchester library to mchr3k's on Github for the ESP32, I have to roll my own.
I noticed I was not able to properly decode the signals from one of my two sensor boards and started digging into it. What I found was a difference in encoding HIGH and LOW bits in terms of phase lengths. The sensor board showed a significant shift of the HIGH signal towards shorter phase lengths, despite the fact the code in the Manchester lib is using the very same delays:
void Manchester::sendZero(void)
{
delayMicroseconds(delay1);
digitalWrite(TxPin, HIGH);
delayMicroseconds(delay2);
digitalWrite(TxPin, LOW);
}//end of send a zero
void Manchester::sendOne(void)
{
delayMicroseconds(delay1);
digitalWrite(TxPin, LOW);
delayMicroseconds(delay2);
digitalWrite(TxPin, HIGH);
}//end of send one
On the receiver side the signals show up as follows. I grouped the signal lengths in larger categories to keep it manageable. In the table you will find from left to right: Category#, Base phase length of that category, number of hits for a '0' signal, number of hits for an '1' signal:
Cat Phas 0 1
-------------------
0 0: 1 0
1 59: 0 0
2 118: 0 0
3 177: 0 0
4 236: 0 0
5 295: 0 4
6 354: 0 49
7 413: 47 0
8 472: 5 0
9 531: 0 0
10 590: 0 0
11 649: 0 0
12 708: 0 1
13 767: 0 25
14 826: 20 0
15 885: 6 0
You can see the '1' signal is shifted at least one category down towards shorter phase lengths.
How can that happen? I already changed the ATtiny85, the 433MHz sender and put fresh batteries in (the board is driven by 2 AAA batteries and a step-up converter to 3.3V) with no change at all.
The ATtiny will wake up every 8s and start reading the sensors and sending the data every 7th turn.
Please find the ATtiny85 sketch below.
/*
ATtiny85 sensor
*/
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <TinyWireM.h>
#include "MyAttinyBME280.h"
#define _BH1750FVI
#ifdef _BH1750FVI
#define BH1750_ADDRESS 0x23
#endif
// include Manchester code library to drive 433MHz sender
#include <Manchester.h>
// Sensor data structure
#include "SensorData.h"
// *********** Define I/O Pins **********************
const int BatteryLvl = A2; // Battery input
const int DATA_433 = PIN_B1; // 433MHz sender data wire
//************ USER PARAMETERS***********************
// Number of sleep cycles between actions
const uint8_t SLEEPCYCLES = 7;
SensorData s;
// Variables for the Sleep/power down modes:
volatile uint8_t f_wdt = SLEEPCYCLES;
//************* MyAttinyBMP280 object ***************
MyAttinyBME280 bme(0x76);
// Routines to set and clear bits (used in the sleep code)
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
// the setup routine runs once when you press reset:
void setup() {
// Set up IO pins
pinMode(BatteryLvl, INPUT);
pinMode(DATA_433, OUTPUT); // 433 MHz sender
analogReference(INTERNAL);
// Initialize 433MHz sender
man.setupTransmit(DATA_433, MAN_1200);
s.data.len = 11;
s.data.magic = 0x72;
s.data.typeID = 0x11;
TinyWireM.begin();
// Sets BME280 forced mode, no upsampling
bme.setWeatherMonitoring();
bme.init();
setup_watchdog(9); // approximately 8 seconds sleep
}
// the loop routine runs over and over again forever:
void loop() {
if (f_wdt>=SLEEPCYCLES) { // wait for timed out watchdog / flag is set when a watchdog timeout occurs
f_wdt=0; // reset cycles
bme.startSingleMeas();
float fval = 0.0;
uint16_t val = 0;
// Temperature
fval = bme.readTemp();
val = (fval+50)*500;
s.data.payload[0] = (val>>8)&0xff;
s.data.payload[1] = val&0xff;
// Pressure
fval = bme.readPress();
val = (fval-600)*100;
s.data.payload[2] = (val>>8)&0xff;
s.data.payload[3] = val&0xff;
// Humidity
fval = bme.readHumidity();
val = fval * 655;
s.data.payload[4] = (val>>8)&0xff;
s.data.payload[5] = val&0xff;
#ifdef _BH1750FVI
TinyWireM.beginTransmission(BH1750_ADDRESS); // I2C address
TinyWireM.write(0x20); // Switch to H-Mode2 1Lux resolution, one time
TinyWireM.endTransmission();
delay(150);
TinyWireM.requestFrom(BH1750_ADDRESS, 2); // Request 2 bytes
if(TinyWireM.available()) // Request 2 bytes
{
s.data.payload[6] = TinyWireM.read(); // Read byte into array
s.data.payload[7] = TinyWireM.read(); // Read byte into array
}
#endif
// Batteriestatus
sbi(ADCSRA,ADEN); // switch Analog to Digitalconverter ON, in case we will need it
int volt = 0;
for(uint8_t i=8; i; i--) volt += analogRead(BatteryLvl);
volt >>= 3;
s.data.battery = (volt >> 2);
cbi(ADCSRA,ADEN); // switch Analog to Digitalconverter OFF again
man.transmitArray(12, s.packet); // Send data
}
// now sleep well :-)
system_sleep();
}
// set system into the sleep state
// system wakes up when wtchdog is timed out
void system_sleep() {
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_enable();
sleep_mode(); // System actually sleeps here
sleep_disable(); // System continues execution here when watchdog timed out
}
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(int ii) {
byte bb;
int ww;
if (ii > 9 ) ii=9;
bb=ii & 7;
if (ii > 7) bb|= (1<<5);
bb|= (1<<WDCE);
ww=bb;
MCUSR &= ~(1<<WDRF);
// start timed sequence
WDTCR |= (1<<WDCE) | (1<<WDE);
// set new watchdog timeout value
WDTCR = bb;
WDTCR |= _BV(WDIE);
}
// Watchdog Interrupt Service / is executed when watchdog timed out
ISR(WDT_vect) {
f_wdt++; // set global flag
}