chipKIT® Development Platform

Inspired by Arduino™

UNO32 with RFM12B wireless

Created Tue, 05 Nov 2013 05:43:35 +0000 by thinkpeace


thinkpeace

Tue, 05 Nov 2013 05:43:35 +0000

I'm currently using the Arduino UNO for a garden controller, and I am looking into using the UNO32.

The garden controller is receiving data from sensor modules using the RFM12B low-power, low-cost wireless wireless device. The sensor moudles are based on the Arudiono compatible Moteino's (http://lowpowerlab.com/moteino/) - these will remain the same.

Would I be able to compile this library to run on the UNO32? The library I'm using is from JeeLabs, https://github.com/jcw/jeelib. The Arduino resources used include the SPI port, 1 interrupt pin, and the EEPROM to read configuration settings.

If it needs porting, would this be a difficult task?

Thanks in advance


guymc

Fri, 08 Nov 2013 14:46:29 +0000

Well, I don't have any experience with the JeeLabs sensor library. But in general, it depends on whether the original library respects the standard Arduino abstraction layer. If it does, then the code will most likely just work.

If the library writes to the hardware registers directly, then some porting will be required. Often it is simply a case of removing (or commenting out) the direct hardware code, and using the abstraction layer instead. Since chipKIT boards generally run much faster than original Arduino, direct access to hardware registers is rarely needed.


thinkpeace

Fri, 27 Dec 2013 06:29:50 +0000

I tried compiling the project I'm porting from Arduino in MPIDE, and the RFM12B library is giving me an error. I fixed numerous errors by replacing the the implementation of SPI which was using AVR code with calls to the SPI library.

I still have some code that doesn't compile:

// access the RFM12B internal registers with interrupts disabled
  bitClear(EIMSK, INT0);
  uint16_t r = XFERSlow(cmd);
  bitSet(EIMSK, INT0);

EIMSK and INT0 are not defined.

Also, when I searched out interrupt examples using the UNO32, it was very simple with just a pinMode call, and an attachInterrupt call. I didn't find anything using the Arduino library to enable and disable specific interrupts.

Do I need to use PIC specific registers to do this, or is there some Arduino library function I could use?

Thanks


majenko

Fri, 27 Dec 2013 10:59:13 +0000

The chipKIT equivalent to cli() and sei() is DisableInterrupts() and EnableInterrupts(). This affects all interrupts.

You can directly manipulate the individual interrupts by setting / clearing bits in the various IECx registers - they're detailed in the data sheet for the chip on your board.


thinkpeace

Thu, 16 Jan 2014 00:38:57 +0000

Thanks for your help.

I got everything working on the Arduino UNO and on the Moteino with all the AVR specific code replaced.

I did this by modifying the LowPowerLab's version of the RFM12 library (https://github.com/LowPowerLab/RFM12B). I verified that it works on the Arduino UNO, and on the Moteino using the LED Control Demo (https://github.com/LowPowerLab/RFM12B/tree/master/Examples/LED_Control_Gateway).

The code I ran on the Arduino UNO compiled without error on the ChipKit. I ran the same code on the ChipKit wf32, and it doesn't work. I having it running the LED Control Gateway code, and as soon as I try to send a command to the LED Control Node, it hangs up, and nothing is received on the node.

To eliminate wiring mistakes, I connected the ChipKit to an RFM12B on a bread board, side-by-side with an Arduino UNO which is working successfully, and verified that they are connected identically (less the resistors to convert from 5v to 3.3v on the Arduino).

I'm connecting the RFM12B as shown on this page: http://openenergymonitor.org/emon/buildingblocks/rfm12b-wireless, except that I'm using Pin 9 for the SS rather than pin 10.

I've attached the modified RFM12B library.

What could be causing it not to work?


thinkpeace

Fri, 17 Jan 2014 21:22:54 +0000

I haven't got this working yet.

If anyone with the needed skills thinks the RFM12B or RFM69W would be useful, or would be an interesting project to work on, I'm willing to purchase two transceivers for you so you can help get it to work on the WF32 and other ChipKit boards.

Any takers?

The ChipKit WF32 would make a great gateway for a network of Moteino's http://lowpowerlab.com/moteino/


thinkpeace

Sat, 18 Jan 2014 22:08:58 +0000

I put an LED on the interrupt line and on the SS line.

When I attempt to transmit, the interrupt line goes low and stays low. It seems like it is never getting to the interrupt handler, because the interrupt handler should be doing SPI transfers continuously until the interrupt is cleared.

I would expect the SS led to dim as long as the interrupt was low, but it is not dimming.

Any suggestions?


thinkpeace

Sat, 18 Jan 2014 22:59:49 +0000

I got it working finally!

I figured out first that the interrupt 0 is on pin 3 on the WF32, and second that the PIC32 does not support level interrupts - only RISING, FALLING or CHANGE.

I modified the interrupt handler by wrapping it up in a loop, so it continues until the interrupt pin goes high. I changed the interrupt mode from LOW to FALLING.

do
{
   // Interrupt code here

} while( digitalRead( 3 ) == 0 )

Now the LED Control demo is working, and the WF32 board is communicating with a moteino. The encryption is not working yet, though I don't need it at this time.

I'll post the library somewhere when I have it cleaned up.


majenko

Sat, 18 Jan 2014 23:12:57 +0000

There's no such thing as a "level" interrupt. An interrupt occurs on an event - a steady state (level) isn't an event, only a change from one state to another (an edge).


thinkpeace

Sun, 19 Jan 2014 00:09:53 +0000

The RFM library on the arduino is configured to interrupt on Low.
The interrupt handler would get called repeatedly as long as the interrupt pin is low. The Pic32 does not have this mode.


thinkpeace

Sun, 19 Jan 2014 00:12:15 +0000

The RFM library on the arduino is configured to interrupt on Low.
The interrupt handler would get called repeatedly as long as the interrupt pin is low. The Pic32 does not have this mode.


majenko

Sun, 19 Jan 2014 00:24:11 +0000

Another great reason to stay well away from Atmel. Whoever came up with the idea of triggering an interrupt on a steady state like LOW needs stringing up. That's just a completely insane idea! That's not what interrupts do! You can't repeatedly trigger an interrupt like that when there is no event to trigger on. That truly was a bizarre design choice, and I'll wager dollars to doughnuts that the engineers that had to implement it really hate the manager that came up with the idea - and that certainly is a manager's idea, not an engineer's idea.

Idiots.

In systems programming, an interrupt is a signal to the processor emitted by hardware or software indicating an event that needs immediate attention. An interrupt alerts the processor to a high-priority condition requiring the interruption of the current code the processor is executing, the current thread. The processor responds by suspending its current activities, saving its state, and executing a small program called an interrupt handler (or interrupt service routine, ISR) to deal with the event. This interruption is temporary, and after the interrupt handler finishes, the processor resumes execution of the previous thread.

... How can it resume its current activities if the "event" that caused the interrupt is still going on, and could be for the rest of eternity for all we know? Surely it'll be trying to interrupt again while it's doing the interrupting that's interrupting the interrupt that was interrupted by the interrupt...

It really is horribly vile, I'm sorry.


thinkpeace

Sun, 19 Jan 2014 05:19:31 +0000

It's not a completely insane idea. The a level interrupt lends it self to multiple devices sharing the same interrupt line.

For example, lets say device A and device B are both connected to a level interrupt line. The interrupt line would be an OR of the two devices. The ISR routine always checks the devices for pending service needed, first A and then B. Device B asserts an interrupt and the ISR will service device B. Before the ISR completes, device A asserts an interrupt. The ISR would immediately get re-entered and device A would get serviced.

Lets assume it was edge triggered and we had two devices on the same line. Device B asserts an interrupt, and while the ISR is servicing device B, device A asserts an interrupt. Because it is edge triggered, this second trigger is missed, and never gets serviced.


majenko

Sun, 19 Jan 2014 10:44:36 +0000

Oh I know all that, but it doesn't stop them being vile. You rely on the device causing the interrupt releasing the interrupt line in a timely fashion, or you risk triggering the interrupt again when you shouldn't. It's all very well on a shared bus with a strict protocol including rigid timing specifications, like a PCI bus, but for a small microcontroller with effectively only one interrupt (no proper priority levels) it's just not on.

You have to service your interrupt as fast as possible in order to service other interrupts. If your ISR takes ages servicing these interrupts other interrupts aren't going to have a chance to happen. You can create a much much more reliable system by triggering on an edge, adding the event to an event queue, and leaving the ISR. Then your event queue is processed outside the ISR giving other interrupts (from the same source, or other sources) a chance to be serviced.

It's fine on a high-end MCU or a full blown computer where you have multiple interrupt priorities, but not when you only have one or at most two priorities and nothing much can happen while you're inside an ISR.


dougBrist

Thu, 20 Mar 2014 06:19:27 +0000

Thanks for the help thinkpeaceyou've save me potentially days of time!

I had been working on integrating the JeeLabs RFM12B library with my UNO32 and a the Modtronics RFM12B Breakout Boards ([url]http://modtronicsaustralia.com/shop/rfm12b-breakout-board-wireless-module/[/url]) - which I reckon are better than the JeeLabs RFM12B boards - and ran into the same problem as you. I didn't know enough about the standard AVR Arduino to be able to fix it. So thanks very much for posting your solution, really appreciate it.

Cheers,

Doug