1

I am working on a small RF sensor powered by a battery. I used the code from Mr K. (https://arduino.stackexchange.com/a/55516/65870) as base and adapted it to the RH Ask protocol:

#define F_CPU 8000000  // This is used by delay.h library

#include <util/delay.h> #include <avr/sleep.h> #include <avr/wdt.h> #include <util/crc16.h>

#define LED_PIN 0

#define TX_PIN 4 //3 #define TX_BAUDRATE 2000 #define TX_MILLIINTERVAL (1000UL/TX_BAUDRATE) #define TX_MICROINTERVAL (1000000UL/TX_BAUDRATE) #define TX_MAXLEN 12 #define RFRepetitions 3 byte RollingCounter = 0;

// Define sensor IDs (for MQTT) #define SensorIDMoisture 6

// Define moisture sensor variables #define MoistureSensorPinA A1 #define MoistureSensorPinD 10 #define MoisturePowerOutPin 1 #define RFPowerPin 3 //4

inline void led(const bool onOff) { digitalWrite(LED_PIN, onOff ? HIGH : LOW); } inline void tx(const bool onOff) { digitalWrite(TX_PIN, onOff ? HIGH : LOW); }

const uint8_t header[8] = { 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x38, 0x2C }; const uint8_t conv4to6[16] = { 0x0D, 0x0E, 0x13, 0x15, 0x16, 0x19, 0x1A, 0x1C, 0x23, 0x25, 0x26, 0x29, 0x2A, 0x2C, 0x32, 0x34 };

// Watchdog timer #ifndef cbi #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #endif #ifndef sbi #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #endif

// Important: Sleep time equals the wdt_length setting multiplied by the wdt_loops_max #define wdt_loops_max 225 #define wdt_length 9 // 9 = 8 seconds

volatile int wdt_loops = wdt_loops_max; // Start with maximum value in order to have a measurement when powering on the system

void rawSend(const uint8_t * p, uint8_t len) { while (len--) { const uint8_t val = *p++; for (uint8_t mask = 1; mask != 0x40; mask <<= 1) { tx(val & mask); delayMicroseconds(TX_MICROINTERVAL);

// _delay_ms(TX_MILLIINTERVAL); } } }

void send(const uint8_t * buf, const uint8_t len) { #define RH_ASK_HEADER_LEN 4 // First create the payload ... static uint8_t payload[(TX_MAXLEN+3+RH_ASK_HEADER_LEN)*2]; uint8_t * p = payload; uint16_t crc = 0xFFFF; uint8_t v = len + 3 + RH_ASK_HEADER_LEN; crc = _crc_ccitt_update(crc, v); p++ = conv4to6[v >> 4]; p++ = conv4to6[v & 0x0F];

uint8_t _txHeaderTo = 0xff; uint8_t _txHeaderFrom = 0xff; uint8_t _txHeaderId = 0; uint8_t _txHeaderFlags = 0;

// Encode the headers
crc = _crc_ccitt_update(crc, _txHeaderTo);
*p++ = conv4to6[_txHeaderTo &gt;&gt; 4];
*p++ = conv4to6[_txHeaderTo &amp; 0xf];
crc = _crc_ccitt_update(crc, _txHeaderFrom);
*p++ = conv4to6[_txHeaderFrom &gt;&gt; 4];
*p++ = conv4to6[_txHeaderFrom &amp; 0xf];
crc = _crc_ccitt_update(crc, _txHeaderId);
*p++ = conv4to6[_txHeaderId &gt;&gt; 4];
*p++ = conv4to6[_txHeaderId &amp; 0xf];
crc = _crc_ccitt_update(crc, _txHeaderFlags);
*p++ = conv4to6[_txHeaderFlags &gt;&gt; 4];
*p++ = conv4to6[_txHeaderFlags &amp; 0xf];


for (uint8_t l = len; l--;) { v = buf++; crc = _crc_ccitt_update(crc, v); p++ = conv4to6[v >> 4]; p++ = conv4to6[v & 0x0F]; } crc = ~crc; v = (uint8_t)crc; p++ = conv4to6[v >> 4]; p++ = conv4to6[v & 0x0F]; v = (uint8_t)(crc >> 8); p++ = conv4to6[v >> 4]; *p++ = conv4to6[v & 0x0F];

// Now transmit the header and the payload ... rawSend(header, sizeof(header)); rawSend(payload, (len + 3 + RH_ASK_HEADER_LEN)*2); tx(false);

//Serial.print("CRC: ");Serial.println(crc); }

ISR(WDT_vect) { wdt_loops++; }

// Sleep void system_sleep() { cbi(ADCSRA,ADEN); // switch Analog to Digitalconverter OFF

set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here sleep_enable();

sleep_mode(); // System sleeps here

sleep_disable(); // System continues execution here when watchdog timed out sbi(ADCSRA,ADEN); // switch Analog to Digitalconverter ON }

// Setup for Watchdog 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); }

void setup() /----( SETUP: RUNS ONCE )----/ { // pinMode(LEDPin, OUTPUT); pinMode(LED_PIN, OUTPUT); led(false);

// Initialize moisture sensor pinMode(MoistureSensorPinD, INPUT);

// RF sensor initialization //driver.init();

setup_watchdog(wdt_length); // approximately 8 seconds sleep

}/--(end setup )---/

void loop() /----( LOOP: RUNS CONSTANTLY )----/ { if(wdt_loops >= wdt_loops_max) { //digitalWrite(LEDPin, HIGH); led(true);

wdt_loops = 0;
moisture_measurement();

led(false);

}
system_sleep();

}/* --(end main loop )-- */

void moisture_measurement() { // Activate sensor analogWrite(MoisturePowerOutPin,255);
analogWrite(RFPowerPin,255); _delay_ms(150);

// Turn On RF transmitter

float MoistureMedian = 0; // float sensorValue; for(int i = 0;i<=100;i++) { float sensorValue = analogRead(MoistureSensorPinA); // moisture_percentage = ( 100 - ( (sensorValue/1023.00) * 100 ) ); // moistureSensorSum += moisture_percentage;

MoistureMedian += ( 1 - ( (sensorValue/1023.00) * 1 ) );
//delay(1);
_delay_ms(1);

}

// Read digital values bool digitalValue = digitalRead(MoistureSensorPinD);

// Switch off sensor analogWrite(MoisturePowerOutPin,0);

// Transmit value TransmitSensorValue(SensorIDMoisture,MoistureMedian);

_delay_ms(150); // Turn Off RF transmitter analogWrite(RFPowerPin,0);

}

void MessageEncrypt(int adressIn, int parameterIn, float payloadIn, byte pByteArray[]) { pByteArray[0] = (byte)adressIn;

byte * payloadBArray = (byte *)&payloadIn; pByteArray[1] = payloadBArray[0]; pByteArray[2] = payloadBArray[1]; pByteArray[3] = payloadBArray[2]; pByteArray[4] = payloadBArray[3];

RollingCounter = RollingCounter + 1; if(RollingCounter > 2) RollingCounter = 0;

pByteArray[5] = RollingCounter; }

//CRC-8 - based on the CRC8 formulas by Dallas/Maxim //code released under the therms of the GNU GPL 3.0 license byte CRC8(const byte data, byte len) { byte crc = 0x00; while (len--) { byte extract = data++; for (byte tempI = 8; tempI; tempI--) { byte sum = (crc ^ extract) & 0x01; crc >>= 1; if (sum) { crc ^= 0x8C; } extract >>= 1; } }

return crc; }

void TransmitSensorValue(int SensorID, float SensorValue) { byte MessageOut[6]; MessageEncrypt(SensorID, 1, SensorValue, MessageOut);

for(int i=0;i&lt;RFRepetitions;i++)
{
  send((const uint8_t *)&amp;MessageOut, sizeof(MessageOut));
}  

}

The code runs like a dream as long as I use 2000 as baudrate. As soon as I use another baudrate (500 or 1000) my test receiver does not receive any messages.

Any ideas what is going wrong here?

Thanks :)

MrBen
  • 21
  • 2

1 Answers1

1

I found the problem. I used 2 2032 battery to power the attiny85. The internal clock of the chip is not precise enough when running at 6V. To solve the issue I removed 1 battery. The alternative would be to set the baudrate of the transmitter and receiver to different values (I had to set the receiver to 520 bdps to receive the messages from the transmitter with 500 bdps).

Maybe somebody can reuse my code for his project.

MrBen
  • 21
  • 2