mirror of
https://github.com/grillbaer/esp32-geiger-counter.git
synced 2025-12-21 21:33:03 +01:00
Added WiFi connection to thingspeak (unfinished, requires better
reconnect and more)
This commit is contained in:
25
.cproject
25
.cproject
@@ -19,13 +19,6 @@
|
|||||||
<builder buildPath="${workspace_loc:/Arduino_ESP32_Geiger}/Release" id="io.sloeber.sketch.builder.966698240" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Arduino sketch builder" superClass="io.sloeber.sketch.builder"/>
|
<builder buildPath="${workspace_loc:/Arduino_ESP32_Geiger}/Release" id="io.sloeber.sketch.builder.966698240" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Arduino sketch builder" superClass="io.sloeber.sketch.builder"/>
|
||||||
<tool id="io.sloeber.tool.sketch.compiler.cpp.1981005346" name="Arduino C++ Compiler" superClass="io.sloeber.tool.sketch.compiler.cpp">
|
<tool id="io.sloeber.tool.sketch.compiler.cpp.1981005346" name="Arduino C++ Compiler" superClass="io.sloeber.tool.sketch.compiler.cpp">
|
||||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="io.sloeber.compiler.cpp.sketch.option.incpath.1251431701" name="Include Paths (-I)" superClass="io.sloeber.compiler.cpp.sketch.option.incpath" valueType="includePath">
|
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="io.sloeber.compiler.cpp.sketch.option.incpath.1251431701" name="Include Paths (-I)" superClass="io.sloeber.compiler.cpp.sketch.option.incpath" valueType="includePath">
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/core/core}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/core/variant}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/libraries/U8g2/src}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/libraries/SPI/src}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/libraries/Wire/src}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/libraries/Time}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/libraries/ESP32/src}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/core/core}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/core/core}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/core/variant}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/core/variant}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/ESP32/src}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/ESP32/src}""/>
|
||||||
@@ -33,18 +26,12 @@
|
|||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/Time}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/Time}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/U8g2/src}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/U8g2/src}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/Wire/src}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/Wire/src}""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/WiFi/src}""/>
|
||||||
</option>
|
</option>
|
||||||
<inputType id="io.sloeber.compiler.cpp.sketch.input.704589672" name="CPP source files" superClass="io.sloeber.compiler.cpp.sketch.input"/>
|
<inputType id="io.sloeber.compiler.cpp.sketch.input.704589672" name="CPP source files" superClass="io.sloeber.compiler.cpp.sketch.input"/>
|
||||||
</tool>
|
</tool>
|
||||||
<tool id="io.sloeber.tool.compiler.c.814948982" name="Arduino C Compiler" superClass="io.sloeber.tool.compiler.c">
|
<tool id="io.sloeber.tool.compiler.c.814948982" name="Arduino C Compiler" superClass="io.sloeber.tool.compiler.c">
|
||||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="io.sloeber.compiler.c.sketch.option.incpath.1874159930" name="Include Paths (-I)" superClass="io.sloeber.compiler.c.sketch.option.incpath" valueType="includePath">
|
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="io.sloeber.compiler.c.sketch.option.incpath.1874159930" name="Include Paths (-I)" superClass="io.sloeber.compiler.c.sketch.option.incpath" valueType="includePath">
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/core/core}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/core/variant}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/libraries/U8g2/src}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/libraries/SPI/src}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/libraries/Wire/src}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/libraries/Time}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/libraries/ESP32/src}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/core/core}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/core/core}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/core/variant}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/core/variant}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/ESP32/src}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/ESP32/src}""/>
|
||||||
@@ -52,18 +39,12 @@
|
|||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/Time}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/Time}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/U8g2/src}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/U8g2/src}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/Wire/src}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/Wire/src}""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/WiFi/src}""/>
|
||||||
</option>
|
</option>
|
||||||
<inputType id="io.sloeber.compiler.c.sketch.input.1892783216" name="C Source Files" superClass="io.sloeber.compiler.c.sketch.input"/>
|
<inputType id="io.sloeber.compiler.c.sketch.input.1892783216" name="C Source Files" superClass="io.sloeber.compiler.c.sketch.input"/>
|
||||||
</tool>
|
</tool>
|
||||||
<tool id="io.sloeber.tool.sketch.compiler.s.1002677074" name="Arduino Assembler" superClass="io.sloeber.tool.sketch.compiler.s">
|
<tool id="io.sloeber.tool.sketch.compiler.s.1002677074" name="Arduino Assembler" superClass="io.sloeber.tool.sketch.compiler.s">
|
||||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="io.sloeber.compiler.asm.sketch.option.incpath.134772337" name="Include Paths (-I)" superClass="io.sloeber.compiler.asm.sketch.option.incpath" valueType="includePath">
|
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="io.sloeber.compiler.asm.sketch.option.incpath.134772337" name="Include Paths (-I)" superClass="io.sloeber.compiler.asm.sketch.option.incpath" valueType="includePath">
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/core/core}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/core/variant}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/libraries/U8g2/src}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/libraries/SPI/src}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/libraries/Wire/src}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/libraries/Time}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/Arduino_ESP32_Geiger/libraries/ESP32/src}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/core/core}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/core/core}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/core/variant}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/core/variant}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/ESP32/src}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/ESP32/src}""/>
|
||||||
@@ -71,6 +52,7 @@
|
|||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/Time}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/Time}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/U8g2/src}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/U8g2/src}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/Wire/src}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/Wire/src}""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${workspace_loc:/esp32-geiger-counter/libraries/WiFi/src}""/>
|
||||||
</option>
|
</option>
|
||||||
<inputType id="io.sloeber.compiler.S.sketch.input.1759766211" name="Assembly source files" superClass="io.sloeber.compiler.S.sketch.input"/>
|
<inputType id="io.sloeber.compiler.S.sketch.input.1759766211" name="Assembly source files" superClass="io.sloeber.compiler.S.sketch.input"/>
|
||||||
</tool>
|
</tool>
|
||||||
@@ -96,4 +78,5 @@
|
|||||||
</storageModule>
|
</storageModule>
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||||
|
<storageModule moduleId="refreshScope"/>
|
||||||
</cproject>
|
</cproject>
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
/Release/
|
/Release/
|
||||||
/sloeber.ino.cpp
|
/sloeber.ino.cpp
|
||||||
/spec.d
|
/spec.d
|
||||||
|
/credentials.h
|
||||||
|
|||||||
5
.project
5
.project
@@ -61,6 +61,11 @@
|
|||||||
<type>2</type>
|
<type>2</type>
|
||||||
<locationURI>ECLIPSE_HOME/arduinoPlugin/libraries/U8g2/2.25.10</locationURI>
|
<locationURI>ECLIPSE_HOME/arduinoPlugin/libraries/U8g2/2.25.10</locationURI>
|
||||||
</link>
|
</link>
|
||||||
|
<link>
|
||||||
|
<name>libraries/WiFi</name>
|
||||||
|
<type>2</type>
|
||||||
|
<location>C:/dev/git/arduino-esp32/libraries/WiFi</location>
|
||||||
|
</link>
|
||||||
<link>
|
<link>
|
||||||
<name>libraries/Wire</name>
|
<name>libraries/Wire</name>
|
||||||
<type>2</type>
|
<type>2</type>
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include "U8g2lib.h"
|
|
||||||
|
|
||||||
#include "driver/pcnt.h"
|
#include "driver/pcnt.h"
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "driver/rtc_io.h"
|
#include "driver/rtc_io.h"
|
||||||
|
|
||||||
|
#include "display.h"
|
||||||
|
#include "ingest.h"
|
||||||
#include "GeigerData.h"
|
#include "GeigerData.h"
|
||||||
|
|
||||||
// ~400<30>s high pulses from Geiger tube on GPIO 18
|
// ~400<30>s high pulses from Geiger tube on GPIO 18
|
||||||
#define PULSE_PIN 18
|
#define PULSE_PIN 18
|
||||||
#define PULSE_GPIO GPIO_NUM_18
|
#define PULSE_GPIO GPIO_NUM_18
|
||||||
|
|
||||||
// OLED display 128x64 with SH1106 controller
|
// switch input for WiFi on (low) and off (high)
|
||||||
// on I2C GPIOs SCL 22 and SDA 21
|
#define WIFI_SWITCH_PIN 4
|
||||||
U8G2_SH1106_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, 22, 21);
|
|
||||||
|
|
||||||
// Keep 600 samples of 1s in history (10 minutes),
|
// Keep 600 samples of 1s in history (10 minutes),
|
||||||
// calculate radiation for russian STS-6 ("CTC-6") Geiger tube
|
// calculate radiation for russian STS-6 ("CTC-6") Geiger tube
|
||||||
@@ -32,12 +32,15 @@ const uint32_t sampleMicros = geigerData.sampleSeconds * 1000000;
|
|||||||
// Absolute sample interval start micros
|
// Absolute sample interval start micros
|
||||||
uint32_t sampleStart = 0;
|
uint32_t sampleStart = 0;
|
||||||
|
|
||||||
|
const int16_t ingestInterval = 60;
|
||||||
|
int16_t ingestCountdown;
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(921600);
|
Serial.begin(921600);
|
||||||
|
Serial.println("Starting!");
|
||||||
|
|
||||||
// high I2c clock still results in about 100ms buffer transmission to OLED:
|
// OLED
|
||||||
u8g2.setBusClock(1000000);
|
initDisplay();
|
||||||
u8g2.begin();
|
|
||||||
|
|
||||||
// blinky
|
// blinky
|
||||||
pinMode(LED_BUILTIN, OUTPUT);
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
@@ -45,8 +48,16 @@ void setup() {
|
|||||||
// Geiger pulse input
|
// Geiger pulse input
|
||||||
pinMode(PULSE_PIN, INPUT);
|
pinMode(PULSE_PIN, INPUT);
|
||||||
|
|
||||||
|
// WiFi switch input
|
||||||
|
pinMode(WIFI_SWITCH_PIN, INPUT_PULLUP);
|
||||||
|
|
||||||
|
if (wifiSwitchOn()) {
|
||||||
|
initIngest();
|
||||||
|
}
|
||||||
|
|
||||||
// initialize sample start
|
// initialize sample start
|
||||||
sampleStart = micros();
|
sampleStart = micros();
|
||||||
|
ingestCountdown = ingestInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// interrupt handler
|
// interrupt handler
|
||||||
@@ -55,16 +66,29 @@ void pulse() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t calcRemainingWait() {
|
uint32_t calcRemainingWait() {
|
||||||
return sampleMicros - (micros() - sampleStart);
|
const uint32_t remaining = sampleMicros - (micros() - sampleStart);
|
||||||
|
return remaining > sampleMicros ? 0 : remaining;
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
boolean wifiSwitchOn() {
|
||||||
|
return digitalRead(WIFI_SWITCH_PIN) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
// blinky
|
uint16_t takeSampleNoSleep() {
|
||||||
|
attachInterrupt(PULSE_PIN, pulse, RISING);
|
||||||
|
|
||||||
digitalWrite(LED_BUILTIN, blinky);
|
int32_t remainingWait = calcRemainingWait();
|
||||||
blinky = !blinky;
|
delayMicroseconds(remainingWait);
|
||||||
|
sampleStart = micros();
|
||||||
|
noInterrupts();
|
||||||
|
const int16_t pulses = intPulseCount;
|
||||||
|
intPulseCount = 0;
|
||||||
|
interrupts();
|
||||||
|
|
||||||
|
return pulses;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t takeSampleLowPower() {
|
||||||
// To save battery power, use light sleep as much as possible.
|
// To save battery power, use light sleep as much as possible.
|
||||||
// During light sleep, no counters or interrupts are working.
|
// During light sleep, no counters or interrupts are working.
|
||||||
// Therefore simply wake up on each pulse signal change. This
|
// Therefore simply wake up on each pulse signal change. This
|
||||||
@@ -123,9 +147,30 @@ void loop() {
|
|||||||
pulseCount = 0;
|
pulseCount = 0;
|
||||||
intPulseCount = 0;
|
intPulseCount = 0;
|
||||||
|
|
||||||
|
return pulses;
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
// blinky
|
||||||
|
|
||||||
|
digitalWrite(LED_BUILTIN, blinky);
|
||||||
|
blinky = !blinky;
|
||||||
|
|
||||||
|
const uint16_t pulses =
|
||||||
|
wifiSwitchOn() ? takeSampleNoSleep() : takeSampleLowPower();
|
||||||
|
|
||||||
geigerData.addPulses(pulses);
|
geigerData.addPulses(pulses);
|
||||||
geigerData.nextSample();
|
geigerData.nextSample();
|
||||||
|
|
||||||
|
if (wifiSwitchOn()) {
|
||||||
|
ingestCountdown--;
|
||||||
|
if (ingestCountdown <= 0) {
|
||||||
|
ingestCountdown = ingestInterval;
|
||||||
|
ingest(geigerData, ingestInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// determine current value, average 6 seconds
|
// determine current value, average 6 seconds
|
||||||
// because this is very near to the 5 seconds history
|
// because this is very near to the 5 seconds history
|
||||||
// bar width and gives nicely rounded count values
|
// bar width and gives nicely rounded count values
|
||||||
@@ -152,82 +197,5 @@ void loop() {
|
|||||||
Serial.print(" ");
|
Serial.print(" ");
|
||||||
Serial.println(uSphStr);
|
Serial.println(uSphStr);
|
||||||
|
|
||||||
// render cpm and <20>S/h displays
|
updateDisplay(geigerData, uSphStr, cpmStr);
|
||||||
|
|
||||||
u8g2.clearBuffer();
|
|
||||||
uint16_t y = 14;
|
|
||||||
uint16_t xCpm = 56;
|
|
||||||
uint16_t xUSph = 127;
|
|
||||||
u8g2.setFont(u8g2_font_crox4hb_tr);
|
|
||||||
|
|
||||||
u8g2_uint_t w = u8g2.getStrWidth(uSphStr);
|
|
||||||
u8g2.setCursor(xUSph - w, y);
|
|
||||||
u8g2.print(uSphStr);
|
|
||||||
|
|
||||||
w = u8g2.getStrWidth(cpmStr);
|
|
||||||
u8g2.setCursor(xCpm - w, y);
|
|
||||||
u8g2.print(cpmStr);
|
|
||||||
|
|
||||||
y = 21;
|
|
||||||
u8g2.setFont(u8g2_font_4x6_tf);
|
|
||||||
w = u8g2.getStrWidth("<EFBFBD>S/h");
|
|
||||||
u8g2.setCursor(xUSph - w, y);
|
|
||||||
u8g2.print("<EFBFBD>S/h");
|
|
||||||
w = u8g2.getStrWidth("cnt/min");
|
|
||||||
u8g2.setCursor(xCpm - w, y);
|
|
||||||
u8g2.print("cnt/min");
|
|
||||||
|
|
||||||
// history bar graph
|
|
||||||
|
|
||||||
const uint16_t bars = 120;
|
|
||||||
const uint16_t maxBarHeight = 40;
|
|
||||||
const uint16_t samplesPerBar = geigerData.sampleCount / bars;
|
|
||||||
const uint16_t barsPerMinute = 60
|
|
||||||
/ (samplesPerBar * geigerData.sampleSeconds);
|
|
||||||
|
|
||||||
// determine max value for y scale:
|
|
||||||
uint16_t offset = geigerData.getCurrentSample() % samplesPerBar + 1;
|
|
||||||
uint32_t maxPulses = 0;
|
|
||||||
for (int16_t i = 0; i < bars - 1; i++) {
|
|
||||||
const uint32_t prevPulses = geigerData.getPreviousPulses(offset,
|
|
||||||
samplesPerBar);
|
|
||||||
if (prevPulses > maxPulses)
|
|
||||||
maxPulses = prevPulses;
|
|
||||||
offset += samplesPerBar;
|
|
||||||
}
|
|
||||||
const float maxUSph = geigerData.toMicroSievertPerHour(maxPulses,
|
|
||||||
samplesPerBar);
|
|
||||||
const float uSphPerPixel = maxUSph > 40. ? 10. : maxUSph > 4. ? 1. :
|
|
||||||
maxUSph > 0.4 ? 0.1 : 0.01;
|
|
||||||
|
|
||||||
// labels and grid
|
|
||||||
u8g2.setFont(u8g2_font_4x6_tn);
|
|
||||||
char s[10];
|
|
||||||
for (uint16_t i = 10; i <= maxBarHeight; i += 10) {
|
|
||||||
u8g2.setCursor(0, 63 - i + 3);
|
|
||||||
if (uSphPerPixel >= 0.1)
|
|
||||||
sprintf(s, "%.0f", i * uSphPerPixel);
|
|
||||||
else
|
|
||||||
sprintf(s, ".%.0f", i * uSphPerPixel * 10);
|
|
||||||
u8g2.print(s);
|
|
||||||
for (int16_t x = 127 - barsPerMinute; x >= 8; x -= barsPerMinute) {
|
|
||||||
u8g2.drawPixel(x, 63 - i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// bars
|
|
||||||
offset = geigerData.getCurrentSample() % samplesPerBar + 1;
|
|
||||||
for (int16_t i = 0; i < bars - 1; i++) {
|
|
||||||
const uint32_t prevPulses = geigerData.getPreviousPulses(offset,
|
|
||||||
samplesPerBar);
|
|
||||||
const float uSph = geigerData.toMicroSievertPerHour(prevPulses,
|
|
||||||
samplesPerBar);
|
|
||||||
offset += samplesPerBar;
|
|
||||||
uint16_t barHeight = 1 + (int) (uSph / uSphPerPixel);
|
|
||||||
if (barHeight > 40)
|
|
||||||
barHeight = 40;
|
|
||||||
u8g2.drawVLine(127 - i, 63 - barHeight, barHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
u8g2.sendBuffer();
|
|
||||||
}
|
}
|
||||||
|
|||||||
100
display.cpp
Normal file
100
display.cpp
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
#include "U8g2lib.h"
|
||||||
|
|
||||||
|
#include "display.h"
|
||||||
|
|
||||||
|
// OLED display 128x64 with SH1106 controller
|
||||||
|
// on I2C GPIOs SCL 22 and SDA 21
|
||||||
|
U8G2_SH1106_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, 22, 21);
|
||||||
|
|
||||||
|
void initDisplay() {
|
||||||
|
// high I2c clock still results in about 100ms buffer transmission to OLED:
|
||||||
|
u8g2.setBusClock(1000000);
|
||||||
|
u8g2.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderDigits(char uSphStr[16], char cpmStr[16]) {
|
||||||
|
uint16_t y = 14;
|
||||||
|
uint16_t xCpm = 56;
|
||||||
|
uint16_t xUSph = 127;
|
||||||
|
|
||||||
|
u8g2.setFont(u8g2_font_crox4hb_tr);
|
||||||
|
u8g2_uint_t w = u8g2.getStrWidth(uSphStr);
|
||||||
|
u8g2.setCursor(xUSph - w, y);
|
||||||
|
u8g2.print(uSphStr);
|
||||||
|
|
||||||
|
w = u8g2.getStrWidth(cpmStr);
|
||||||
|
u8g2.setCursor(xCpm - w, y);
|
||||||
|
u8g2.print(cpmStr);
|
||||||
|
|
||||||
|
y = 21;
|
||||||
|
u8g2.setFont(u8g2_font_4x6_tf);
|
||||||
|
w = u8g2.getStrWidth("<EFBFBD>S/h");
|
||||||
|
u8g2.setCursor(xUSph - w, y);
|
||||||
|
u8g2.print("<EFBFBD>S/h");
|
||||||
|
|
||||||
|
w = u8g2.getStrWidth("cnt/min");
|
||||||
|
u8g2.setCursor(xCpm - w, y);
|
||||||
|
u8g2.print("cnt/min");
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderHistoryBarGraph(GeigerData &geigerData) {
|
||||||
|
const uint16_t bars = 120;
|
||||||
|
const uint16_t maxBarHeight = 40;
|
||||||
|
const uint16_t samplesPerBar = geigerData.sampleCount / bars;
|
||||||
|
const uint16_t barsPerMinute = 60
|
||||||
|
/ (samplesPerBar * geigerData.sampleSeconds);
|
||||||
|
|
||||||
|
// determine max value for y scale:
|
||||||
|
uint16_t offset = geigerData.getCurrentSample() % samplesPerBar + 1;
|
||||||
|
uint32_t maxPulses = 0;
|
||||||
|
for (int16_t i = 0; i < bars - 1; i++) {
|
||||||
|
const uint32_t prevPulses = geigerData.getPreviousPulses(offset,
|
||||||
|
samplesPerBar);
|
||||||
|
if (prevPulses > maxPulses)
|
||||||
|
maxPulses = prevPulses;
|
||||||
|
|
||||||
|
offset += samplesPerBar;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float maxUSph = geigerData.toMicroSievertPerHour(maxPulses,
|
||||||
|
samplesPerBar);
|
||||||
|
const float uSphPerPixel = maxUSph > 40. ? 10. : maxUSph > 4. ? 1. :
|
||||||
|
maxUSph > 0.4 ? 0.1 : 0.01;
|
||||||
|
// labels and grid
|
||||||
|
u8g2.setFont(u8g2_font_4x6_tn);
|
||||||
|
char s[10];
|
||||||
|
for (uint16_t i = 10; i <= maxBarHeight; i += 10) {
|
||||||
|
u8g2.setCursor(0, 63 - i + 3);
|
||||||
|
if (uSphPerPixel >= 0.1)
|
||||||
|
sprintf(s, "%.0f", i * uSphPerPixel);
|
||||||
|
else
|
||||||
|
sprintf(s, ".%.0f", i * uSphPerPixel * 10);
|
||||||
|
|
||||||
|
u8g2.print(s);
|
||||||
|
for (int16_t x = 127 - barsPerMinute; x >= 8; x -= barsPerMinute) {
|
||||||
|
u8g2.drawPixel(x, 63 - i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// bars
|
||||||
|
offset = geigerData.getCurrentSample() % samplesPerBar + 1;
|
||||||
|
for (int16_t i = 0; i < bars - 1; i++) {
|
||||||
|
const uint32_t prevPulses = geigerData.getPreviousPulses(offset,
|
||||||
|
samplesPerBar);
|
||||||
|
const float uSph = geigerData.toMicroSievertPerHour(prevPulses,
|
||||||
|
samplesPerBar);
|
||||||
|
offset += samplesPerBar;
|
||||||
|
uint16_t barHeight = 1 + (int) ((uSph / uSphPerPixel));
|
||||||
|
if (barHeight > 40)
|
||||||
|
barHeight = 40;
|
||||||
|
|
||||||
|
u8g2.drawVLine(127 - i, 63 - barHeight, barHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateDisplay(GeigerData &geigerData, char uSphStr[16], char cpmStr[16]) {
|
||||||
|
u8g2.clearBuffer();
|
||||||
|
renderDigits(uSphStr, cpmStr);
|
||||||
|
renderHistoryBarGraph(geigerData);
|
||||||
|
u8g2.sendBuffer();
|
||||||
|
}
|
||||||
9
display.h
Normal file
9
display.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef DISPLAY_H_
|
||||||
|
#define DISPLAY_H_
|
||||||
|
|
||||||
|
#include "GeigerData.h"
|
||||||
|
|
||||||
|
void initDisplay();
|
||||||
|
void updateDisplay(GeigerData &geigerData, char uSphStr[16], char cpmStr[16]);
|
||||||
|
|
||||||
|
#endif /* DISPLAY_H_ */
|
||||||
84
ingest.cpp
Normal file
84
ingest.cpp
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#include <WiFi.h>
|
||||||
|
|
||||||
|
#include "GeigerData.h"
|
||||||
|
|
||||||
|
// WiFi and thingspeak credentials:
|
||||||
|
//const char *wifiSsid = "...";
|
||||||
|
//const char *wifiPassword = "...";
|
||||||
|
//const char *thingspeakApiKey = "...";
|
||||||
|
#include "credentials.h"
|
||||||
|
|
||||||
|
const char *thingsPeakUrl = "api.thingspeak.com";
|
||||||
|
|
||||||
|
void connect() {
|
||||||
|
wl_status_t status = WL_DISCONNECTED;
|
||||||
|
|
||||||
|
while (status != WL_CONNECTED) {
|
||||||
|
WiFi.begin(wifiSsid, wifiPassword);
|
||||||
|
Serial.print("Connecting to WiFi '");
|
||||||
|
Serial.print(wifiSsid);
|
||||||
|
Serial.println("' ...");
|
||||||
|
uint16_t waitRemaining = 10;
|
||||||
|
while ((status = WiFi.status()) != WL_CONNECTED && waitRemaining > 0) {
|
||||||
|
Serial.print(" status=");
|
||||||
|
Serial.println(status);
|
||||||
|
delay(500);
|
||||||
|
waitRemaining--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("WiFi connected!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void initIngest() {
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ingest(GeigerData &geigerData, uint16_t intervalSamples) {
|
||||||
|
WiFiClient client;
|
||||||
|
if (!client.connect(thingsPeakUrl, 80)) {
|
||||||
|
Serial.print("Connecting to '");
|
||||||
|
Serial.print(thingsPeakUrl);
|
||||||
|
Serial.println("' failed");
|
||||||
|
} else {
|
||||||
|
|
||||||
|
const uint32_t pulses = geigerData.getPreviousPulses(1,
|
||||||
|
intervalSamples);
|
||||||
|
const uint32_t cpm = uint32_t(
|
||||||
|
pulses
|
||||||
|
/ ((float) intervalSamples * geigerData.sampleSeconds
|
||||||
|
/ 60.) + 0.5);
|
||||||
|
const float uSph = geigerData.toMicroSievertPerHour(pulses,
|
||||||
|
intervalSamples);
|
||||||
|
|
||||||
|
const String content = "api_key=" + String(thingspeakApiKey)
|
||||||
|
+ "&field1=" + String(cpm) + "&field2=" + String(uSph);
|
||||||
|
|
||||||
|
Serial.println("Ingesting");
|
||||||
|
|
||||||
|
client.print("POST /update HTTP/1.1\n");
|
||||||
|
|
||||||
|
client.print("Host: ");
|
||||||
|
client.print(thingsPeakUrl);
|
||||||
|
client.print("\n");
|
||||||
|
|
||||||
|
client.print("Connection: close\n");
|
||||||
|
|
||||||
|
client.print("Content-Type: application/x-www-form-urlencoded\n");
|
||||||
|
client.print("Content-Length: ");
|
||||||
|
client.print(content.length());
|
||||||
|
client.print("\n\n");
|
||||||
|
|
||||||
|
client.print(content);
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
Serial.print("Response: ");
|
||||||
|
while (client.available()) {
|
||||||
|
char c = client.read();
|
||||||
|
Serial.write(c);
|
||||||
|
}
|
||||||
|
Serial.println();
|
||||||
|
|
||||||
|
client.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user