Closed tferrin closed 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.
Hey I did what you've suggested: can you tell me if it works?
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.
No problem, thanks for the report!
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)
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.
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!
@tferrin The changes have been made! Tell me if that's good for you and if there are other things.
Thanks! :)
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.
Oh, thanks for the note! I'll try this soon. In France there is such an heavy process to get any radioactive source.
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.
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)
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.