MonsieurV / ArduinoPocketGeiger

Arduino library to interface with the Radiation Watch Pocket Geiger
MIT License
25 stars 8 forks source link

Doesn't compile on non-AVR architectures #2

Closed tferrin closed 8 years ago

tferrin commented 8 years ago

RadiationWatch.cpp doesn't run on non-AVR architectures like the ARM SAMD M0 (Arduino Zero) for a couple reasons:

1) The calls to dtostrf() produce compiler errors. The fix for this is straightforward. In RadiationWatch.cpp, just after the line #include "RadiationWatch.h" add the following:

ifndef ARDUINO_ARCH_AVR

include <avr/dtostrf.h>

endif

You'll also need to edit the dtostrf.c library file, as jsmith describes in this thread: http://forum.arduino.cc/index.php?topic=368720.0

2) The two instances of function calls like this: pinMode(PinNumber, INPUT); digitalWrite(PinNumber, HIGH); need to be changed to: pinMode(PinNumber, INPUT_PULLUP); This change is backwards compatible (at least with Ardunio IDE 1.6.5 and later) and so this code works fine on AVR-based systems too.

MonsieurV commented 8 years ago

Hello Tom,

Thanks for the complete report! I'll make the changes at the end of the week, as soon as I have an Arduino at hand.

MonsieurV commented 8 years ago

Hey I did what you've suggested: can you tell me if it works?

tferrin commented 8 years ago

Sorry for the delay; I've been away. Things are not working correctly yet, but I don't know if the problem is in your RadiationWatch code or something I don't understand about the Adafruit Feather Cortex M0 processor board and/or how the Pocket Geiger interfaces to this board. The best I can tell is that interrupts are not being processed correctly, but I need to spend more time debugging to figure out what's wrong. I did discover a few of things:

1) The initialization for the RadiationWatch class is RadiationWatch(sigPin, nsPin, irqSigPin, irqNsPin) but these last two arguments are unnecessary since the Arduino library contains a macro, digitalPinToInterrupt(), that can be used to determine the interrupt number. See https://www.arduino.cc/en/Reference/AttachInterrupt. You could easily define another derived class that only required two arguments and then used digitalPinToInterrupt() to set _signIrq and _noiseIrg in RadiationWatch.cpp. This would be backwards compatible with the current code.

2) It appears that with the Type 5 Pocket Geiger that NS is normally low and SIG is normally high, but in RadiationWatch.cpp it sets both interrupt handlers to be called on the RISING edge of these signals. I haven't decided if this is correct or not, and it may be related to the problems I'm experiencing.

3) Maybe related to the bug with interrupts, but it seems like the calculation of uSv/h depends on the amount of delay in the main loop. In order words...

void loop() { radiationWatch.loop(); }

yields a different result than...

void loop() { radiationWatch.loop(); delay(500); }

and this should not be the case. Again, still trying to debug but it would be good to know if #3 is also true with other Arduino architectures.

MonsieurV commented 8 years ago

No problem, thanks for the report!

  1. You pointed to the right way to do it, I'll make the change this week-end.
  2. We may change to detect RISING edge from NS and FALLING edge from SIG. However if it can change the delay at which the current level variations are detected, it shouldn't - I think - change the change the number of variations detected and thus the results over time.
  3. The uSv/h processing does indeed depend on the time ellapsed, as it is an unit over time. If you had more time, you have a different result. radiationWatch.loop() doesn't rely on an implicit delay in the main loop: it uses the millis() function to determine the time ellapsed between each call. However it is important to not miss radiation evente between each radiationWatch.loop() call: as byte volatile radiationCount can count up to 255 events before overflowing to 0 it is unlikely to happened if the procedure is called frequently in the main loop of your program (if it does happened, you better move to another place to consider the issue! ahah).

When you execute this example does the interrupt routines are triggered? (if so it must print messages to the Serial port in presence of noise or radiation events)

tferrin commented 8 years ago

I fixed my problem with interrupts not working by simply upgrading from Arduino IDE 1.6.8 to 1.6.9 and then updating the relevant M0 board support libraries. Obviously the support for the Cortex M0 processor is still evolving and bugs are still getting worked out. But interrupts are working now and I'm getting better results with my Pocket Geiger board.

It would be nice if there was a value accessible via the RadiationWatch class that provided "instantaneous" gamma ray counts instead of the averaged cpm over the last 20 minutes like cpm() provides. In other words, the current value of the variable "radiationCount". This value is buried in the csvStatus() text but not otherwise directly accessible. Of course most of the time it will be zero, but if you have a gamma ray source available for testing (like me) then it's possible for the counts to change dramatically over a short period and it would be nice to know the values.

Why is radiationCount a byte and not an int? Yes bytes can be incremented in one instruction on architectures like the AVR, but int's only take 2 or 3 instructions and the difference is negligible.

MonsieurV commented 8 years ago

For no particular reason, except to preserve the scarce SRAM space of Arduino Uno. We can use an unsigned int: actually I have not tested with a radiation source and it may overflow with a byte.

I'll make these changes as soon as I have an Arduino at reach. It will be nice to know how it behaves with a source!

MonsieurV commented 8 years ago

@tferrin The changes have been made! Tell me if that's good for you and if there are other things.

Thanks! :)

tferrin commented 8 years ago

Tested and all works great! Thank you for updating an already outstanding library. Let's mark this issue resolved.

With respect to int vs byte for radiationCount, I think this was a good change to make. I tested my Pocket Geiger board with a 1 uCurie Ba-133 source and got ~165 cps (10,000 cpm). Of course this is an unusually high count for any real-world environment other than for testing purposes, and additionally calling radiationWatch.loop() every 1s or longer would mean either a very slow processor or lots of intervening code-processing taking place, but 165 is nevertheless near the 256 overflow count for a byte. Changing to an int alleviates this potential problem altogether.

And a bit off-topic, but something I wanted to mention for those in countries that restrict access to samples of radioactive sources: the tungsten electrodes used in MIG (metal inert gas) welding often contains either 1% or 2% thorium, a naturally occurring radioactive element. Such electrodes will likely be available at many welding supply stores. Although primarily an alpha emitter, thorium daughter decay products do include gamma emitters and thus can provide a radiation source for testing Pocket Geiger boards. My 2% thoriated tungsten electrode produces ~130 counts per minute when held in contact with the PG sensor.

MonsieurV commented 8 years ago

Oh, thanks for the note! I'll try this soon. In France there is such an heavy process to get any radioactive source.

MonsieurV commented 8 years ago

Ok, I've gone to my local welding supply store, and they don't sell anymore thoriated tungsten electrode, due to health hazard for the operators (ingestion of particules during sharpening of the electrode). The seller said it was prohibed as a welding material, but I haven't found anything supporting that claim: surely it is just not sold anymore by the distributors.

For French people see:

Anyway, there is internet.

MonsieurV commented 8 years ago

radbox thorium

With the 2% thoriated electrodes under the PG sensor, which still have its beta-shield. It does emmit some gamma rays! :)

(Note: this is measured with my RadBox project, which links a PG sensor to a Raspberry Pi and provides a web interface to consult and share the readings, or set mail for threshold notifications. Presentation coming on my blog)