From ce0cd4bdafacbaee74eba78f15acccf5488a5a36 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Sun, 5 Jul 2020 21:43:08 +0200 Subject: add anemometer app --- src/app/wetterstation/Makefile.inc | 1 + src/app/wetterstation/client.py | 108 +++++++++++++++++++++++++++++++++++++ src/app/wetterstation/main.cc | 44 +++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 src/app/wetterstation/Makefile.inc create mode 100755 src/app/wetterstation/client.py create mode 100644 src/app/wetterstation/main.cc diff --git a/src/app/wetterstation/Makefile.inc b/src/app/wetterstation/Makefile.inc new file mode 100644 index 0000000..2cb8a42 --- /dev/null +++ b/src/app/wetterstation/Makefile.inc @@ -0,0 +1 @@ +loop ?= 1 diff --git a/src/app/wetterstation/client.py b/src/app/wetterstation/client.py new file mode 100755 index 0000000..5bc2afc --- /dev/null +++ b/src/app/wetterstation/client.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 + +import numpy as np +import re +import requests +import serial +import serial.threaded +import sys +import time + +class SerialReader(serial.threaded.Protocol): + """ + Character- to line-wise data buffer for serial interfaces. + + Reads in new data whenever it becomes available and exposes a line-based + interface to applications. + """ + def __init__(self, callback): + """Create a new SerialReader object.""" + self.callback = callback + self.recv_buf = '' + + def __call__(self): + return self + + def data_received(self, data): + """Append newly received serial data to the line buffer.""" + try: + str_data = data.decode('UTF-8') + self.recv_buf += str_data + + # We may get anything between \r\n, \n\r and simple \n newlines. + # We assume that \n is always present and use str.strip to remove leading/trailing \r symbols + # Note: Do not call str.strip on lines[-1]! Otherwise, lines may be mangled + lines = self.recv_buf.split('\n') + if len(lines) > 1: + self.recv_buf = lines[-1] + for line in lines[:-1]: + self.callback(str.strip(line)) + + except UnicodeDecodeError: + pass + #sys.stderr.write('UART output contains garbage: {data}\n'.format(data = data)) + +class SerialMonitor: + """SerialMonitor captures serial output for a specific amount of time.""" + + def __init__(self, port: str, baud: int, callback): + """ + Create a new SerialMonitor connected to port at the specified baud rate. + + Communication uses no parity, no flow control, and one stop bit. + Data collection starts immediately. + """ + self.ser = serial.serial_for_url(port, do_not_open=True) + self.ser.baudrate = baud + self.ser.parity = 'N' + self.ser.rtscts = False + self.ser.xonxoff = False + + try: + self.ser.open() + except serial.SerialException as e: + sys.stderr.write('Could not open serial port {}: {}\n'.format(self.ser.name, e)) + sys.exit(1) + + self.reader = SerialReader(callback = callback) + self.worker = serial.threaded.ReaderThread(self.ser, self.reader) + self.worker.start() + + def close(self): + """Close serial connection.""" + self.worker.stop() + self.ser.close() + +if __name__ == '__main__': + + got_data = False + step = 0 + + def parse_line(line): + + global got_data + + match = re.match('Anemometer Count = ([^ ]+)', line) + if match: + got_data = True + wind_clicks = float(match.group(1)) + windspeed_kmh = wind_clicks * 2.4 / 10 + requests.post('http://influxdb:8086/write?db=sensors', data='anemometer,area=hm17_,location=balkon windspeed_kmh={}'.format(windspeed_kmh)) + + monitor = SerialMonitor('/dev/serial/by-path/platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.1:1.0-port0', 57600, parse_line) + + try: + while True: + time.sleep(5) + + step += 1 + + if step == 4: + if not got_data: + print('Error: received no data for 20 seconds', file=sys.stderr) + sys.exit(1) + got_data = False + step = 0 + + except KeyboardInterrupt: + monitor.close() diff --git a/src/app/wetterstation/main.cc b/src/app/wetterstation/main.cc new file mode 100644 index 0000000..2c47d78 --- /dev/null +++ b/src/app/wetterstation/main.cc @@ -0,0 +1,44 @@ +#include "arch.h" +#include "driver/gpio.h" +#include "driver/stdout.h" + +#include + +volatile uint16_t anemometer_count = 0; + +void loop(void) +{ + static uint8_t loop_count = 0; + static uint16_t anemometer_copy; + if (++loop_count == 10) { + + cli(); + anemometer_copy = anemometer_count; + anemometer_count = 0; + sei(); + + kout << "Anemometer Count = " << anemometer_copy << endl; + loop_count = 0; + } +} + +int main(void) +{ + arch.setup(); + gpio.setup(); + kout.setup(); + + gpio.output(GPIO::pd2, 0); + gpio.input(GPIO::pd3, 1); + + EICRA = _BV(ISC11); + EIMSK = _BV(INT1); + + arch.idle_loop(); + + return 0; +} + +ISR(INT1_vect) { + anemometer_count++; +} -- cgit v1.2.3