Martin's corner on the web

New RFM2Pi board in the works

Glyn Hudson and I have been working on a new RFM2Pi board revision, nothing revolutionary, just a small upgrade. The most important features of the board are:

  • Atmega328 based, has more memory and hardware serial support
  • Runs on the internal 8Mhz oscillator (to save unnecessary components)
  • SMT used, board layout is optimized for pick-and-place machine; SMT also means it is lower profile compared to the old version thus more compatible with Raspberry Pi enclosures
  • The new RFM2Pi allows programming directly from Raspberry Pi using avrdude (..and OptiBoot)

The board schematics and layout are available on github.

I have few test boards, here is how it looks (this one is hand-built, the solder flux not cleaned yet):

IMG_1900

To be able to upload sketches to it, we need OptiBoot installed first. Setting it up is relatively easy (the boards in the shop will come with OptiBoot and the RFM12 demo sketch already installed).

Basically you need a special build for OptiBoot optimized for running on the internal oscillator @ 8Mhz and the optimal for this speed baud rate of 38.4kbps. Excellent work in this setup is described here, let me outline most important steps:

    • Add a new build option to OptiBoot’s makefile
# Standard atmega328, only at 38,400 baud for closer clock accuracy AND using 8Mhz internal RC oscillator
#
atmega328_384_8: TARGET = atmega328
atmega328_384_8: MCU_TARGET = atmega328p
atmega328_384_8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
atmega328_384_8: AVR_FREQ = 8000000L
atmega328_384_8: LDSECTIONS  = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
atmega328_384_8: $(PROGRAM)_atmega328_384_8.hex
atmega328_384_8: $(PROGRAM)_atmega328_384_8.lst

atmega328_384_8_isp: atmega328
atmega328_384_8_isp: TARGET = atmega328
atmega328_384_8_isp: MCU_TARGET = atmega328p
# 512 byte boot, SPIEN
atmega328_384_8_isp: HFUSE = DE
# Int. RC Osc. 8MHz, slowly rising power-65ms 
atmega328_384_8_isp: LFUSE = E2
# 2.7V brownout
atmega328_384_8_isp: EFUSE = 05
atmega328_384_8_isp: isp
    •  I also changed pin_defs.h to asjust for the LED pin
#define LED_DDR     DDRB
#define LED_PORT    PORTB
#define LED_PIN     PINB
#define LED         PINB1
    •  Then run “omake atmega328_384_8” , if you run onto errors, make sure to grab the latest optiboot.c
    • Then we need to add a new entry to our arduino-1.0.1\hardware\arduino\boards.txt. Add an entry like this:
##############################################################

atmega328_384_8.name=ATmega328 Optiboot @ 38,400baud w/ 8MHz Int. RC Osc.

atmega328_384_8.upload.protocol=arduino
atmega328_384_8.upload.maximum_size=30720
atmega328_384_8.upload.speed=38400

atmega328_384_8.bootloader.low_fuses=0xE2
atmega328_384_8.bootloader.high_fuses=0xDE
atmega328_384_8.bootloader.extended_fuses=0x05
atmega328_384_8.bootloader.path=optiboot
atmega328_384_8.bootloader.file=optiboot_atmega328_384_8.hex
atmega328_384_8.bootloader.unlock_bits=0x3F
atmega328_384_8.bootloader.lock_bits=0x0F

atmega328_384_8.build.mcu=atmega328p
atmega328_384_8.build.f_cpu=8000000L
atmega328_384_8.build.core=arduino
atmega328_384_8.build.variant=standard

So with these settings in, I was able to upload the modified OptiBoot using my usbtiny ISP programmer.

I have included a pre-compiled OptiBoot in my github repo.

Next, I plugged the board onto my Raspberry Pi. There is a problem in using avrdude directly, there is a good write up about the issue here, but JCW uses a custom tcl script to upload sketches which he didn’t share. The problem is basically to reset the board at the right time and therfore invoke the bootloader so that avrdude can start talking to it. I researched on the available options to work around the issue and found an elegant 2 minute solution by Dean Mao. Basically he uses strace to determine the exact moment when avrdude wants to reset the target board and uses a small python script to perform the reset. The fix is applied as follows:

  • Make sure you have python installed on your Pi:
sudo apt-get update 
sudo apt-get install python-dev&&python-rpi.gpio
  • Grab the modified code for the RFM2Pi board from my repo and apply the fix:
cp autoreset /usr/bin
cp avrdude-autoreset /usr/bin
mv /usr/bin/avrdude /usr/bin/avrdude-original
ln -s /usr/bin/avrdude-autoreset /usr/bin/avrdude

With these fixes applied, I was able to use avrdude and upload the RFDemo sketch directly from RaspberryPi:

avrdude -v -c arduino -p ATMEGA328P -P /dev/ttyAMA0 -b 38400 -U flash:w:RF12_Demo_atmega328.cpp.hex

Neat 🙂

[update] The board is now available for sale in the shop

 

31 thoughts on “New RFM2Pi board in the works

  1. James Maupin

    Hi Martin, greetings from the US. I’ve been following your RFM2Pi, and not having a tiny84 at hand, I already built one using a Mega328 with a resonator, since I already had that and didn’t need to modify Optiboot (laziness kicked in). I have my Pi set up with an expansion cable to a breadboard and the RFM2Pi on the breadboard, and the setup works quite well for the test phase of my build. I do intend to create a board to mount on the header as soon as I complete the tests. I wanted to stay at 16MHz so I can try to push the serial to 115200, the default console rate.

    I have the Pi feeding data to emoncms.org and wish to have the Pi furnish time data to the GLCD. I saw the series of posts on doing this, but the php script has changed since the posts, and I am unsure what needs to go where in the raspberrypi_run.php script. I could use a wee bit of help on that if you don’t mind. I would think that should be incorporated in a future release of the _run script. So what if the RFM2Pi sends time and nobody is there to hear it.

    Regards,

  2. Martin Harizanov Post author

    Hi,
    The appropriate place to insert that fragment wold be right after the script inserts the received data i.e. after this line:

    // Run the input processor (new to call new version of the input processor..)
    new_process_inputs($userid,$inputs);

    I’d also implement a timer so that time is sent at most once a minute, not upon each post to emoncms.

    if (time()-$todtimer>60)
    {
    $todtimer = time();

    …send time
    }

    I also think that should be merged in to the code, please do issue a pull request when you manage it

  3. James Maupin

    Hi Martin, I’ve made the changes you recommended and by the gods it works! Thanks for the pointer. In case someone else needs this, here is a Cliff’s Notes version of what I did…

    Open Terminal and log in as pi, then

    cd /var/www/emoncms/Modules/raspberrypi
    sudo nano raspberrypi_run.php

    Look for these 2 lines (@195/196 on 25Feb13)…
    // Run the input processor (new to call new version of the input processor..)
    new_process_inputs($userid,$inputs);

    Then add this chunk below those two lines …

    if (time()-$todtimer>60)
    {
    $todtimer = time();

    $hour = date(‘H’);
    $min = date(‘i’);
    fprintf($f,$hour.”,00,”.$min.”,00,s”);
    sleep(1);
    }

    Do the CTRL-X,Y,[ENTER] thing, then restart mysql …

    sudo /etc/init.d/mysql restart

    Then in HomeEnergyMonitor in loop() in the time updating section change rf12_data[1] to rf12_data[0] like so…

    if (node_id == 1 || node_id == 2) // for me, node 1 = nanode, node 2 = pi, set to your system nodes
    {
    digitalWrite(greenLED, HIGH); // flash the LED to indicate the time is updated
    while( rf12_data[0] > 23) // fixes the hour when returned from emoncms,
    { // which returns GMT which results in a negative
    rf12_data[0] += 24; // number from 1800 to midnight in US CTZ
    } // which the rtc can’t understand.

    RTC.adjust(DateTime(2013, 2, 25, rf12_data[0], rf12_data[2], rf12_data[3]));
    last_emonbase = millis();
    delay(25);
    digitalWrite(greenLED, LOW);
    }

  4. Jérôme

    Hi guys.

    Following the discussion here [1] about raspberry_run.php, I’m working on a python rewrite of the RFM2Pi gateway [2]. It is working, already, though it stills needs a little bit of work (hardcoded parameters) before asking for integration.

    This time feature seems like an easy one. I can even make it optional.

    I don’t have the emonGLCD to test it, though. Can you please clarify or point me to an explanation of the time format ?

    The php code here :

    $hour = date(‘H’);
    $min = date(‘i’);
    fprintf($f,$hour.”,00,”.$min.”,00,s”);

    yields

    09,00,57,00,s

    Is this correct ?

    Congratulations Martin for the new board !

    [1] https://github.com/emoncms/raspberrypi/issues/5
    [2] https://github.com/Jerome-github/emoncms_raspberrypi/blob/raspberrypi_run_python_script/rfm2pigateway.py

    1. Martin Post author

      Jerome,
      some impressive work you have done 🙂

      Yes, this is the string we need to pass to the RFM2Pi board in order to have it send out time.

      Cheers,
      Martin

      1. Jérôme

        Thank you Martin.

        I am using a “RFM12Pi Raspberry Pi Expansion board kit (433 Mhz)”, pre-loaded with your software. which I understand is this sketch :
        https://github.com/mharizanov/RFM2Pi/blob/master/firmware/RFM2Pi_RF12_Demo/TinySensor_RF12_Demo/TinySensor_RF12_Demo.ino

        Here’s what I get on the serial port :

        2013-03-02 19:22:04,282 INFO Serial RX: 10 182 6
        (node 10, temperature)

        2013-03-02 19:00:54,584 INFO Serial RX: > 15i
        2013-03-02 19:00:54,589 INFO Serial RX: > 4b
        2013-03-02 19:00:54,594 INFO Serial RX: > 210g
        (apparently the board repeats on the serial link what I just sent it, as an acknowledgement I guess)

        Now, when I try to send “09,00,57,00,s”, for instance

        ser.write(“09,00,57,00,s”)

        I get

        2013-03-02 19:24:05,003 INFO Serial RX: > 0s
        2013-03-02 19:24:05,009 INFO Serial RX: -> 4 b

        Is this normal behaviour ? Could I be doing anything wrong ?

        Is there a page that lists all the inputs I can expect from the serial port ?

        Thanks.

  5. Martin Post author

    Hi, the output looks normal, it acknowledges that it sent 4 bytes so you see the “4b”
    Browse the code to see how it works, basically is is a simplified version of JCW’s RF12Demo sketch https://github.com/jcw/jeelib/tree/master/examples/RF12/RF12demo

    It seems to have better documentation, however the version I use is stripped down of much functionality to fit the Attiny84 8K limit. You can safely ignore lines starting with “>” in your code, these are just info messages. I assume you have sen the way emoncms handles this in PHP https://github.com/emoncms/raspberrypi/blob/master/raspberrypi_run.php

  6. Jérôme

    Yes, I used raspberry_run.php as an example.

    I do trash the > messages, but here, I’m receiving “->” (see the minus sign).

    2013-03-02 19:46:12,880 INFO Serial RX: > 0s
    2013-03-02 19:46:12,885 INFO Serial RX: -> 4 b

    From your answer, I would expect something like :

    2013-03-02 19:46:12,885 INFO Serial RX: > 4 b

    I’ll read your link. Thanks.

  7. Martin Post author

    Ah, yes it is actually a ” ->”, note the leading space
    Since the original raspberry_pi.run doesn’t do time sends, it has no handling of this case. You can then just add a rule to ignore lines starting with ” ” and “>” 🙂

  8. Jérôme

    Ah, ok then.

    First I strip of blank spaces to get something like [’10’, ‘132’, ‘123’] or [‘->’, ‘4’, ‘b’].

    Then, I discard all frames beginning with either ‘>’ or ‘->’ as information messages.

    And I’m logging a warning if
    – number of elements is not odd and at least 3
    – all elements are not integers

    I still don’t understand the “> 0s” I receive.

    I read the page you pointed me to :
    https://github.com/jcw/jeelib/tree/master/examples/RF12/RF12demo
    It is not a comprehensive description of the dialog format, more like a startup tutorial, and I didn’t spend much time in the code, I must admit.

    It says

    10. In the above test, you’re sending packets with no actual data other than
    what the protocol itself requires to function properly. To include some test
    data use “1,2,3,0s” or “1,2,3,0a” with “1,2,3” being the actual data. This
    sends a test packet with 3 data bytes (you can send up to 66 data bytes).
    The “t” commands is available as shorthand for “0,1,2,…,63,64,65,0a”.

    Should we send “09,00,57,00s” instead of “09,00,57,00,s” ?

    Anyway, from my (receiver) side it seems to work. At least the program does not crash on unhandled RX frames. I don’t have any emonGLCD to test.

  9. Jérôme

    There seems to be another case I don’t manage : the help message…

    At least it is interpreted as a misformed message, but the script does not crash.

    2013-03-12 11:09:47,516 INFO Serial RX:
    2013-03-12 11:09:47,519 WARNING Misformed RX frame: [”]
    2013-03-12 11:09:48,628 INFO Serial RX: Available commands:
    2013-03-12 11:09:48,631 WARNING Misformed RX frame: [‘Available’, ‘commands:’]
    2013-03-12 11:09:49,753 INFO Serial RX: 123 x – Toggle configuration change protection, 1=Unlocked
    2013-03-12 11:09:49,757 WARNING Misformed RX frame: [‘123’, ‘x’, ”, ”, ”, ”, ”, ‘-‘, ‘Toggle’, ‘configuration’, ‘change’, ‘protection,’, ‘1=Unlocked’]
    2013-03-12 11:09:50,880 INFO Serial RX: i – set node ID (standard node ids are 1..26)
    2013-03-12 11:09:50,883 WARNING Misformed RX frame: [”, ‘i’, ”, ”, ”, ”, ‘-‘, ‘set’, ‘node’, ‘ID’, ‘(standard’, ‘node’, ‘ids’, ‘are’, ‘1..26)’]
    2013-03-12 11:09:52,181 INFO Serial RX: b – set MHz band (4 = 433, 8 = 868, 9 = 915)
    2013-03-12 11:09:52,184 WARNING Misformed RX frame: [”, ‘b’, ”, ”, ”, ”, ”, ‘-‘, ‘set’, ‘MHz’, ‘band’, ‘(4’, ‘=’, ‘433,’, ‘8’, ‘=’, ‘868,’, ‘9’, ‘=’, ‘915)’]
    2013-03-12 11:09:53,309 INFO Serial RX: g – set network group (RFM12 only allows 212, 0 = any)
    2013-03-12 11:09:53,312 WARNING Misformed RX frame: [”, ‘g’, ”, ”, ”, ‘-‘, ‘set’, ‘network’, ‘group’, ‘(RFM12’, ‘only’, ‘allows’, ‘212,’, ‘0’, ‘=’, ‘any)’]
    2013-03-12 11:09:54,426 INFO Serial RX: c – set collect mode (advanced, normally 0)
    2013-03-12 11:09:54,430 WARNING Misformed RX frame: [”, ‘c’, ”, ”, ”, ”, ”, ‘-‘, ‘set’, ‘collect’, ‘mode’, ‘(advanced,’, ‘normally’, ‘0)’]
    2013-03-12 11:09:55,549 INFO Serial RX: …, a – send data packet to node , with ack
    2013-03-12 11:09:55,553 WARNING Misformed RX frame: [‘…,’, ‘a’, ‘-‘, ‘send’, ‘data’, ‘packet’, ‘to’, ‘node’, ‘,’, ‘with’, ‘ack’]
    2013-03-12 11:09:56,672 INFO Serial RX: …, s – send data packet to node , no ack
    2013-03-12 11:09:56,676 WARNING Misformed RX frame: [‘…,’, ‘s’, ‘-‘, ‘send’, ‘data’, ‘packet’, ‘to’, ‘node’, ‘,’, ‘no’, ‘ack’]
    2013-03-12 11:09:57,798 INFO Serial RX: l – turn activity LED on DIG8 on or off
    2013-03-12 11:09:57,801 WARNING Misformed RX frame: [”, ‘l’, ”, ”, ”, ”, ”, ‘-‘, ‘turn’, ‘activity’, ‘LED’, ‘on’, ‘DIG8’, ‘on’, ‘or’, ‘off’]
    2013-03-12 11:09:58,912 INFO Serial RX: Current configuration:
    2013-03-12 11:09:58,915 WARNING Misformed RX frame: [‘Current’, ‘configuration:’]
    2013-03-12 11:10:00,033 INFO Serial RX: 79 i15 g210 @ 433 MHz Lock: 1
    2013-03-12 11:10:00,037 WARNING Misformed RX frame: [’79’, ‘i15’, ‘g210’, ‘@’, ‘433’, ‘MHz’, ”, ‘Lock:’, ‘1’]

  10. Pingback: Funky v2 as RFM12B to Raspberry Pi gateway | Martin's corner on the web

  11. Pingback: TCP/IP over RFM12B and Raspberry Pi as gateway | Martin's corner on the web

  12. Pingback: Dirt Cheap Low Power Wireless Sensor Node using nRF24L01+ 2.4GHz | Martin's corner on the web

  13. Tom

    Inspired by your post I managed to create a rfm12pi board with an ATMEGA8 running at 16MHz.

    Thanks for the great posts

  14. rudi van drunen

    Hi all,

    Is there a PDF file of the schematic available ?? Esp. I want to know which pins of the GPIO connector are used.

    Thanks

    Rudi

  15. Pingback: Martin's corner on the web

    1. Martin Post author

      Hi,
      At that time someone was blogging that direct RFM12B SPI connection with the Raspberry Pi caused him significant headaches because of the small buffer that the RFM12B has. That may have changed with more recent kernel versions. Delegating the task to a micro controller made this so much easier. Probably worth re-visiting this option now again, thanks for the heads up!

      1. Oliver

        Thanks!
        …still wondering what might be the best option for me – whether the “extra layer” with the micro controller makes it better or worse… 😉
        Well, anyway, we’ll see – maybe, I should just pick one option and give it a try!

  16. Pingback: NodeRED RFM2Pi to emonCMS gateway | Martin's corner on the web

  17. Johan Kanflo

    Hi Martin,

    I built a board similar to your RFM12Pi board in order to learn basic PCB design and I also used the internal oscillator of the AVR. That did however not work at all, the AVR would hear the RasPi but not the other way around. Checking the raw UART traffic on a logic analyser revealed that the AVR transmitted at about 59kbaud (when set to 57200!) which I interpreted as the internal osc being completely out of whack. Adding an external crystal and saved the day. I noted a comment in raspberrypi_run.php saying that the data out from the RFM2Pi sometimes accidentally changes settings and that the cause might be data corruption. Could using the internal oscillator be the culprit here also?

    Cheers,
    Johan

    1. Martin Post author

      Interesting,
      I haven’t had such case yet, although it totally makes sense. I have tried out internal oscillator calibration on Attinys before, but not on Atmega. Google for it, it uses the UART to adjust OSCCAL http://forum.arduino.cc/index.php/topic,8553.0.html . Could work on Atmega328 with some code adjustment.
      The settings change was another thing (software UART), it was resolved in the v2 of the board by using Atmega328’s hardware uart
      Cheers

  18. Pingback: Interfacing with Paradox home security system attempt 2 | Martin's corner on the web

  19. Pingback: DIY Internet of Things Fire Alarm | Martin's corner on the web

  20. Pingback: MQTT topic tree structure improvements | Martin's corner on the web