Its not "that" bad .. the Attiny44A is compatible with Arduino thanks to https://github.com/SpenceKonde/ATTinyCore
For now I got Humidity and Voltage(VCC) running up fine.
Its not "that" bad .. the Attiny44A is compatible with Arduino thanks to https://github.com/SpenceKonde/ATTinyCore
For now I got Humidity and Voltage(VCC) running up fine.
From time to time I run into this bug .. not sure if this is related:
0;255;3;0;9;TSM:READY:NWD REQ<\n>
0;255;3;0;9;TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=20,pt=0,l=0,sg=0,ft=0,st=OK:<\n>
Fatal exception 28(LoadProhibitedCause):<\n>
epc1=0x40202704, epc2=0x00000000, epc3=0x00000000, excvaddr=0x00000003, depc=0x00000000<\n>
<\r><\n>
I might have run into a bug in the calculation of message length.
In my handcrafted packet I use this as the 4thy byte send:
0b10000001
So to craft this I looked at MyMessage.h which showed me this:
uint8_t version_length; // 2 bit - Protocol version
// 1 bit - Signed flag
// 5 bit - Length of payload
So from my understanding:
Protocol Version = 2 => 0b10
Signed Flag = 0 => 0b0
Length of Payload = 1 = 0b00001
Which results in 0b10 0 00001 = 0b10000001
But I get this error:
LEN,8!=23
So .. where might this come from?
radio.write(test,8);
Mycontroller received a packet with the length of 8 but expected a packet with the length of .. 23 ?!
#define mGetLength(_message) ((uint8_t)BF_GET(_message.version_length, 3, 5)) //!< Get length field
Which in essential is BF_GET ..
#define BF_GET(y, start, len) ( ((y)>>(start)) & BIT_MASK(len) ) //!< Extract a bitfield of length 'len' starting at bit 'start' from 'y'
So what is happening?
BF_GET(0b10000001, 3, 5) ( ((0b10000001)>>(3)) & BIT_MASK(5) ) //!< Extract a bitfield of length 'len' starting at bit 'start'
Whoops? This will throw away all the length-information!!!
(0b10000001)>>(3)
This should result in:
0b11110000 & BIT_MASK5 = 0b1111000 & 0b00011111 = 0b00010000 = 16 decimal
const uint8_t expectedMessageLength = HEADER_SIZE + (mGetSigned(_msg) ? MAX_PAYLOAD : msgLength);
const uint8_t expectedMessageLength = 7+ 16); // = 23
Yeah .. the lib is right .. 8 != 23 .. but the handcrafted length = 1 + header_length (7) = 8
Am I wrong or is this a bug?
Edit: I might have read the comments in the source code the wrong way
After many hours trial and error I present you .. the raw-mysensors-client!!
MyGateway: ESP8266 + mysensorsMQTT
MyNode: https://github.com/Miceuz/PlantWateringAlarm
MyNode-MCU: Attiny44 (MemoryFootprint: 87% of 4KB)
ArduinoCore: https://github.com/SpenceKonde/ATTinyCore
ArduinoCore-PinLayout: Counterclockwise (like AttinyCore)
Note: The default "counterclockwise"pinout is the alternate pinout shown here: https://github.com/SpenceKonde/ATTinyCore/blob/master/avr/extras/ATtiny_x4.md
The important hint is here (http://tmrh20.github.io/RF24/ATTiny.html)
Connect MOSI of the RF24 to PA5 of the attiny and MISO of the RF24 to PA6 of the attiny.
CE = 8
CSN = 7
To get the connection done right DONT .. i mean DO NOT BECAUSE IT DOESNT FUCKING WORK connect MOSI of the RF24 to MOSI of the attiny. RF24 uses a embedded implementation of the USI-engine found on some AtTiny's.
radio-initilisation
radio.begin(); // Start up the radio
radio.setDataRate(RF24_250KBPS);
radio.setAutoAck(1); // Ensure autoACK is enabled
radio.setRetries(15,15); // Max delay between retries & number of retries
//radio.setPayloadSize(8);
radio.enableDynamicPayloads();
radio.setPALevel(RF24_PA_MAX);
byte tx_address[] = { 0x00, 0xFC, 0xE1, 0xA8, 0xA8 };
//byte tx_address[] = { 0xA8, 0xA8, 0xE1, 0xFC, 0x00 };
radio.openWritingPipe(tx_address);
radio.stopListening();
Send-Function:
void sendHumidity(uint16_t humidity)
{
// snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%s/%d/%d/%d/%d/%d"), prefix, message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type);
// X8X22<\0><\n>!<7>7AY0;255;3;0;9;TSF:MSG:READ,50-50-0,s=55,c=1,t=7,pt=1,l=1,sg=0:65<\n>
// 0;255;3;0;9;Sending message on topic: domoticz/in/MyMQTT/50/55/1/0/7<\n>
#define LAST_NODE_ID 50 // last
#define NODE_ID 50 // sender
#define GATEWAY_ID 0 // destination
// version_length // 5 bit - Length of payload // 1 bit - Signed flag // 2 bit - Protocol version
// command_ack_payload // 3 bit - Payload data type // 1 bit - Is ack messsage - Indicator that this is the actual ack message. // 1 bit - Request an ack - Indicator that receiver should send an ack back. // 3 bit - Command type
#define SENSOR_TYPE 7 // type S_HUM = 7
#define SENSOR_ID 55 // sensor-id
byte test[] = { LAST_NODE_ID, NODE_ID, GATEWAY_ID, 0b00010010, 0b01100001, SENSOR_TYPE, SENSOR_ID, (uint8_t)(humidity & 0x00FF), (uint8_t)((humidity >> 8) & 0x00FF), 0x00 };
radio.write(test,9);
}
I am not quite sure yet if the message-types etc. are right but I am trying to find this out. 'A' (dec 65) is the "value" of my humidity .. next step is to make this a real value ofc.
Proof at domoticz:

@gohan: In the file MyConfig.h I commented this out:
/**
* @def MY_REGISTRATION_FEATURE
* @brief If enabled, node has to register to gateway/controller before allowed to send sensor data.
*/
// #define MY_REGISTRATION_FEATURE
This will skip the whole hasse of registering the client properly (which I can't .. remember 87% of flash is full)
@gohan Thanks for your response. The problem is that I already have 5 "chirps" and just later came up with the idea of adding nrf24 to them. I might try to add a "relay" node which will listen for "normal" rf24 packets and then send them to my gateway using the mysensors library.
Hello,
is it possible to "inject" a sensor-value into the gateway by hand-crafting a data packet?
I recently got some of these little guys (https://wemakethings.net/chirp/)
Now my idea was to slap a NRF24 on the ISP header (+2 extra pins for CE and CSN).
So far so good .. now I want to craft a simple packet to get data to my gateways ..
This is what I got so far but my gateway is not picking up anything.
radio.begin(); // Start up the radio
radio.setDataRate(RF24_250KBPS);
radio.setAutoAck(1); // Ensure autoACK is enabled
radio.setRetries(15,15); // Max delay between retries & number of retries
byte station_address[] = { 0x00, 0xFC, 0xE1, 0xA8, 0xA8 };
//byte station_address[] = { 0xA8, 0xA8, 0xE1, 0xFC, 0x00 };
radio.openWritingPipe(station_address); // Write to device address 0x00,0xFC,0xE1,0xA8,0xA8
radio.stopListening();
byte test[] = { 250, 250, 0, 0b10000001 /* version_length */, 0b00100001, 7 /* S_HUM */ , 1 /* V_HUM */, 123};
radio.write(test,8);
And no .. I can't cram the mysensors library on the ATTINY44.
I am currently happe that I got the basic chirp functunality for measuring the humidity of the soil, attiny debug serial and nrf24 all running on 4k of flash.
Der Sketch verwendet **4046 Bytes (98%)** des Programmspeicherplatzes. Das Maximum sind 4096 Bytes.
Globale Variablen verwenden 150 Bytes (58%) des dynamischen Speichers, 106 Bytes für lokale Variablen verbleiben. Das Maximum sind 256 Bytes.
If anybody know if this is even possible I would like to hear from you.
Best regards Marc
@NeverDie: In addition to using RF24_PA_MIN I power most of my nodes from 2x AA Alkaline Batteries .. so they have 2.2V - 3,0V VCC. This might contribute to my pretty good reception.
Earlier nodes used 3,3V LDO in connection with lithium-ion batteries. So I can't say what really improved my reception the most ... lowering the voltage or putting the RF24_PA_MIN.
Just to add my 2cent .. I mainly use the LNA+PA ones (cheap from ebay) and complained some time for their "bad" performance.
Just recently I noticed they are quite nice but .. RF24_PA_MIN is your friend! I got nearly zero packet-loss ~20m (one wall between) with RF24_PA_MIN. This might just be a subjective opinion but as they only cost 2-3$ a piece they are a good option (at least for me).
Getting "genuin" chips for a reasonable price is very difficulty in germany.
At least in theory .. how much power does the ultrasonic-part consume and/or do you switch it off between measurements?
19 days ago .. I hope i dont wake the dead .. on my latest projects I bagen using this nice stuff:
I currently have 5 modules of the "old"-jboard and still 2-3 spare "high"-power modules left. I just recently noticed that most of my communication problems apparently came from RF24_PA_MAX settings. Currently running with RF24_PA_MIN I am very satisfied with the "high"-power modules. Was just inrested int he latest developement.
My recent focus switched over to make some nice housings for my nodes. Having a board+sensors is only half of the work ;-)
Currently I mostly use Alkaline but on some project I use old handy-lipo-batteries. They are nice since they include some basic safety circuits.
Most of my projects work on 2xAA-Alkaline with 1mhz-AVR .. pretty good experience so far .. even with uses ones.
Are these new boards compatible to the old footprint? I think the layout of the "high power"-rf24 versions did not change in the past coulpe of years and I can't rely on the "small"-boards .. got a solid home with conrete falls :D
Its not like "defaultish"-library but currently I am using this piece:
https://github.com/fschaefer/Prescaler/blob/master/prescaler.h
It features some code to get the "real" millis but all librarys that depend on arduino "delay" and "millis" function might do wrong delays/timings.
All my nodes run at 1mhz to power them up with even 2xAA batteries @2,4volt or less. If some nodes have a more stable supply I use the library this way:
uint8_t old_ps = getClockPrescaler();
setClockPrescaler(0x00);
oled.setCursor(0,1);
oled << mymin << "," << sum << "," << mymax << "," << (diff < 1024 ? diff : 1024) << "," << (acc < 1024 ? acc : 1024) << " " << endl;
oled << "sf: " << spike_forgiveness << " " << endl;
oled.setCursor(64,3);
oled.print(readVcc());
oled.print("mV ");
oled.setCursor(0,3);
oled.print(RF24_readByteRegister(OBSERVE_TX),HEX);
setClockPrescaler(old_ps);
Regarding the power-footprint. Are you using the sleep-function of mysn?
@tekka Thanks, that is what I was looking for
@Yveaux While we are at this topic .. any chance to let the user-code know what caused the wakeup during sleep() ??
For example .. if there was a wakeup at all or which of the two interrupt sources was the cause.
Unforunatly the "cause" gets cleaned up at the end of hwSleep:
bool interruptWakeUp()
{
return _wokeUpByInterrupt != INVALID_INTERRUPT_NUM;
}
Calling this from user-code will always return 0 as the end of hwSleep does this:
_wokeUpByInterrupt = INVALID_INTERRUPT_NUM;
Not clearing the "last interrupt source" would be nice.
I only used the pin change interrupt in another sketch. I was doubting Serial in sections without isr too! But they are clever. Serial output depends on polling in sections where interrupts are disabled ;-)
Just copy'pasted your fix and .. voila
Problems seems to be solved - although I do not unterstand why?!
.. even if the interrupt is not detached correctly .. how should it lead to the total skip of these code:
cli();
wdt_reset();
// enable WDT changes
WDTCSR |= (1 << WDCE) | (1 << WDE);
// restore saved WDT settings
WDTCSR = WDTsave;
Serial.println("sei()");
Serial.flush();
sei();
// enable ADC
ADCSRA |= (1 << ADEN);
//WDTCSR |= (1 << WDIE); // set the WDIE flag to enable interrupt callback function.
As this code-snipped is skipped sei() gets never called in my case .. and the subsequent call to i2c freezes the node ... as i2c depends on interrupts ..
Anyway thanks Yveaux .. althour your fix is simple .. i don't know why it is working ...
EDIT: Furthermore .. even if the interrupt is not detached in the isr .. there should be no further interrupt if the interrupt register is not read via i2c .. and that in fact doesn't happen >:>
Jep, this is the library.
https://github.com/mysensors/MySensors/blob/development/core/MyHwATMega328.cpp#L86
https://github.com/mysensors/MySensors/blob/master/core/MyHwATMega328.cpp#L75
well .. I have no idea but on my code it is there:
Seems to be neither in the stable nor the developement branch .. but I most gotten it somewhere .. lets check
I think I added it for some reason on latest stable. Otherwise pinchage-interrupt was not working with mysensors-library .. I will try to remove it on stable to see if I get stuck there too and add in snapshot to see if it helps in some way.
EDIT1: Adding in the latest snapshot doesn't change a thing
EDIT2: Removing it in the latest stable doesn't change a thing
I might have added it from another testsketch .. but it would be better located in that sketch right after the sleep function .. so just ignore it for now - my bad ;_(
Comparing the code to the atmel documentation here:
http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__sleep.html
mysensors explicit disables interrupts after wake from sleep:
sei();
// Directly sleep CPU, to prevent race conditions! (see chapter 7.7 of ATMega328P datasheet)
sleep_cpu();
sleep_disable();
// restore previous WDT settings
cli();
whereas the atmel documentation enables interrupts
#include <avr/interrupt.h>
#include <avr/sleep.h>
...
set_sleep_mode(<mode>);
cli();
if (some_condition)
{
sleep_enable();
sleep_bod_disable();
sei();
sleep_cpu();
sleep_disable();
}
sei();
Might not be totally related as the code did not change from last stable .. except one line:
WDTCSR |= (1 << WDIE); // set the WDIE flag to enable interrupt callback function.
is now missing in the snapshot ..
Adding an extra sei() after the sleep_disable() is not the solution .. still thought it might be noteworthy