Skip to content

Instantly share code, notes, and snippets.

@jaggzh
Created March 16, 2024 04:22
Show Gist options
  • Save jaggzh/7d16c633e8ef42ecfdfd790983083110 to your computer and use it in GitHub Desktop.
Save jaggzh/7d16c633e8ef42ecfdfd790983083110 to your computer and use it in GitHub Desktop.
#include <stdint.h>
#include <cfloat> // FLT_MIN FLT_MAX
#include "driver/adc.h" // use esp-idf directly
#include "printutils.h"
#include "median.h"
#include "wifi.h"
#include "wifi_config.h"
#include "ota.h"
#include "netdata.h"
#define OPT_PLOT_DATA
/* #define OPT_PLOT_COUNT */
#define US_PER_SAMP 45
#define US_PER_60HZ_CYCLE 8333
/* #define BS 120 */
#define BS 150
#define CYCLES 30
#define CHOP BS
#define TRIGGER_FRAC .90
#define SUL static unsigned long
#define UL unsigned long
#define SENCNT 2
int spins[SENCNT] = {34, 35};
adc1_channel_t schans[SENCNT] = {ADC1_CHANNEL_6, ADC1_CHANNEL_7};
#define __min(a,b) ((a)<(b)?(a):(b))
#define __max(a,b) ((a)>(b)?(a):(b))
// State machine states
enum State {
ST_START,
ST_READING,
ST_PROCESSING,
ST_PRINTING
};
// Timing and state management variables
unsigned long highwait_delay_us = 0;
unsigned long lowwait_delay_us = 5000;
unsigned long hightime_us = 0;
unsigned long lowtime_us = 0;
int16_t in1zeros = 0;
int16_t in1ones = 0;
int16_t in1ctr = 0; // Additional counter for tracking the number of processed events
// Calibration thresholds
#define MIN_RATIO_CTR 100
#define MAX_RATIO_CTR (INT16_MAX / 2 - 2)
#define RATIO_CTR_RESET_VAL (MAX_RATIO_CTR - MIN_RATIO_CTR)
State state = ST_START;
int buf_v[BS+1];
float buf_mavg_div[BS+1];
#if 0
void read_cycle(void) {
for (int i=0; i<BS; i++) {
buf_v[i] = adc1_get_raw(IN1ADC_CH);
}
}
void read_cycle_buf(int *b, int len) {
for (int i=0; i<len; i++) {
b[i] = adc1_get_raw(IN1ADC_CH);
}
}
#endif
#define copy_cycle(d,f,len) memcpy(d, f, len*sizeof(*f))
#define espAnalog1ReadCh(ch) adc1_get_raw(ch)
unsigned long us_rising_4isr_st=0;
unsigned long us_rising_4isr_en=0;
void fisr_rising() { us_rising_4isr_en=micros(); }
void merge_cycle_mavg(float *db, float *newb, int div, unsigned int len) {
// merge difference with divider
db[0] = newb[0];
for (int i=1; i<len; i++) {
db[i] += (newb[i] - db[i])/div;
}
}
void merge_cycle_mavg(float *db, int *newb, int div, unsigned int len) {
// merge difference with divider
db[0] = newb[0];
for (int i=1; i<len; i++) {
db[i] += (newb[i] - db[i])/div;
}
}
void get_minmax(float *mnstore, float *mxstore, float *b, int len) {
float mn = FLT_MAX;
float mx = FLT_MIN;
for (int i=0; i<len; i++) {
if (b[i] > mx) mx = b[i];
if (b[i] < mn) mn = b[i];
}
*mnstore = mn;
*mxstore = mx;
}
int find_cnt_at_thresh(float *b, int len, float frac, float mn, float mx) {
float thresh=mn + (mx-mn)*frac;
for (int i=0; i<len; i++) {
if (b[i] > thresh) return i;
}
return -1;
}
void smooth_buf(float *dest, int *src, int len, int window, bool repeat_boundary) {
// Check if the window size is odd, adjust if even to ensure symmetry for smoothing
if (window % 2 == 0) {
window++; // Make window size odd if it's even
}
int halfWindow = window / 2;
for (int i = 0; i < len; i++) {
float sum = 0;
int count = 0;
for (int j = -halfWindow; j <= halfWindow; j++) {
int idx = i + j;
// Handle boundary cases
if (repeat_boundary) {
// Repeat boundary values if outside the array
if (idx < 0) idx = 0;
else if (idx >= len) idx = len - 1;
} else {
// Skip the out-of-bounds indices
if (idx < 0 || idx >= len) continue;
}
sum += src[idx];
count++;
}
dest[i] = sum / count; // Compute the average and assign it to the dest array
}
}
int get_adc1_avg(adc1_channel_t ch, int cnt) {
long sum=0;
for (int i=0; i<cnt; i++)
sum += adc1_get_raw(ch);
return (int)(sum / cnt);
}
/* void toneoutputs() { */
/* for (int chi=0; chi<SENCNT; chi++) */
/* pinMode(spins[chi], INPUT); */
/* pinMode(PIN_PIEZO, OUTPUT); */
/* } */
/* void toneinputs() { */
/* pinMode(PIN_PIEZO, INPUT); */
/* } */
uint16_t lastv[SENCNT];
// doubles
float curmin[SENCNT], curmax[SENCNT];
float slcurmin[SENCNT], slcurmax[SENCNT];
float slv[SENCNT];
float slv2[SENCNT];
float slv3[SENCNT];
float midlinev[SENCNT];
float norminit[SENCNT];
float slvnorm[SENCNT];
// floats
float range[SENCNT];
float rangeoff[SENCNT];
float midrange[SENCNT];
float diffint[SENCNT];
float lastdiff[SENCNT];
float slabsdiff[SENCNT];
float lastabsdiff[SENCNT];
UL btn[SENCNT];
void setup() {
Serial.begin(230400);
delay(2000); // safety so easier to flash if crashing code
// adc currently not unused v v v v
// ch4 = io32
// ch6 = io34
// ch7 = io35
for (int chi=0; chi<SENCNT; chi++) {
adc1_config_width(ADC_WIDTH_BIT_11); // Set ADC res bits
adc1_config_channel_atten(schans[chi], ADC_ATTEN_DB_11);
pinMode(spins[chi], INPUT);
get_adc1_avg(schans[chi], 10); // warmup of readings?
slv3[chi] = slv2[chi] = slv[chi] = get_adc1_avg(schans[chi], 1000);
norminit[chi] = midlinev[chi] = lastv[chi] = slv[chi];
curmin[chi] = curmax[chi] = slv[chi];
curmin[chi] -= .01;
curmax[chi] += .01;
slcurmin[chi] = curmin[chi];
slcurmax[chi] = curmax[chi];
midrange[chi] = 0;
btn[chi] = 0;
}
setup_wifi();
setup_ota();
setup_netdata();
state = ST_READING;
/* delay(1000); */
/* netdata_send_btn1(); */
/* delay(1000); */
/* netdata_send_btn2(); */
/* delay(1000); */
/* attachInterrupt(IN1PIN, fisr_rising, RISING); */
/* delay(50); */
/* read_cycle(); */
/* copy_cycle(buf_mavg_div, buf_v, BS); */
/* toneoutputs(); */
/* for (int i=220; i<400; i+=1) { */
/* tone(PIN_PIEZO, i); */
/* delay(5); */
/* } */
/* noTone(PIN_PIEZO); */
/* toneinputs(); */
/* delay(50); */
}
#define BUFCNT 15
#define BUFOUTLIERS 3
uint16_t bufv[SENCNT][BUFCNT];
// https://gist.github.com/jaggzh/552022494eff43cf2a3712931d315c4d
void loop() {
unsigned long cmillis = millis();
unsigned long cmicros = micros();
static unsigned long last_print_ms = 0;
static unsigned long last_read_us = 0;
static unsigned long last_proc_us = 0;
static unsigned long last_wifi_ms = 0;
#define ADC_MIDDLE 1137
#define ADC_RANGE 1
#define ADC_RANGE_MAX ADC_MIDDLE+1
#define ADC_RANGE_MIN ADC_MIDDLE-1
// used
#define SLOW_DIV 768
#define NORM_DIV 1500 // norm of slow!
#define MIDLINE_DIV (50*1024)
#define MINMAX_TOWARDS_DIV (50*1024)
#define MINMAX_AWAY_DIV (1024)
int diff[SENCNT], absdiff[SENCNT];
uint16_t v[SENCNT];
double trigmin[SENCNT];
double trigmax[SENCNT];
double median[SENCNT];
static UL last_cmillis=cmillis-1;
SUL st_read_ms=cmillis-1, en_proc_ms=cmillis, en_print_ms=cmillis;
// readings
if (state == ST_READING) {
st_read_ms = cmillis;
if (cmicros-last_read_us > 160) { // 150
for (int bi=0; bi<BUFCNT; bi++) {
int newv;
int chi;
for (chi=0; chi<SENCNT; chi++) {
newv=espAnalog1ReadCh(schans[chi]);
bufv[chi][bi] = newv;
delayMicroseconds(1000);
}
}
state = ST_PROCESSING;
}
last_proc_us = cmicros;
} else if (state == ST_PROCESSING) {
for (int chi=0; chi<SENCNT; chi++) {
/* v[chi] = bufv[chi][0]; */
median[chi] = findTrimmedMean(bufv[chi], BUFCNT, BUFOUTLIERS, 1);
/* slv[chi] = findTrimmedMean(bufv[chi], BUFCNT, 2, 0); */
/* #define A_SL .001 */
#define A_SL .2
#define A_SL2 .01
#define A_SL3 .0001
slv[chi] = (median[chi]*(A_SL) + slv[chi]*(1-A_SL));
uint16_t cval=slv[chi];
/* slv2[chi] = (median[chi]*(A_SL2) + slv2[chi]*(1-A_SL2)); */
slv3[chi] = (cval*(A_SL3) + slv3[chi]*(1-A_SL3));
#define A_MMAX_TOWARD .01
#define A_MMAX_AWAY .1
#define A_MMAX_SLOW .07
float mmaxv = median[chi];
if (mmaxv < curmin[chi])
curmin[chi] = mmaxv*(A_MMAX_AWAY) + curmin[chi]*(1-A_MMAX_AWAY);
else if (mmaxv > curmin[chi])
curmin[chi] = mmaxv*(A_MMAX_TOWARD) + curmin[chi]*(1-A_MMAX_TOWARD);
if (mmaxv > curmax[chi])
curmax[chi] = mmaxv*(A_MMAX_AWAY) + curmax[chi]*(1-A_MMAX_AWAY);
else if (mmaxv < curmax[chi])
curmax[chi] = mmaxv*(A_MMAX_TOWARD) + curmax[chi]*(1-A_MMAX_TOWARD);
slcurmin[chi] = curmin[chi]*A_MMAX_SLOW + slcurmin[chi]*(1-A_MMAX_SLOW);
slcurmax[chi] = curmax[chi]*A_MMAX_SLOW + slcurmax[chi]*(1-A_MMAX_SLOW);
/* float range=slcurmax[chi] - slcurmin[chi]; */
float range = 30;
trigmin[chi] = slcurmin[chi] - (range*.5);
trigmax[chi] = slcurmax[chi] + (range*.5);
/* sp('m'); sp(chi); sp(':'); spt(median[chi]); */
/* sp("mn"); sp(chi); sp(':'); spt(trigmin[chi]); */
UL bmillis=millis();
en_proc_ms = bmillis;
#define DEBUG_PLOT_TRIGGERS
/* #define DEBUG_PLOT_TRIGGERS_ALLDATA */
#if defined(DEBUG_PLOT_TRIGGERS) || defined(DEBUG_PLOT_TRIGGERS_ALLDATA)
bool sprinted=false; // for if we need to send a newline
#endif
#ifdef DEBUG_PLOT_TRIGGERS_ALLDATA
sp("d"); sp(chi); sp(':'); spt(trigmin[chi] - median[chi]);
sprinted=true;
#endif
#if 0 && defined(DEBUG_PLOT_TRIGGERS)
static UL last_db_plot=0;
if (cmillis-last_db_plot > 250) {
sp("d"); sp(chi); sp(':'); spt(trigmin[chi] - median[chi]);
sprinted=true;
last_db_plot=cmillis;
}
#endif
int sendbutton=0;
if (trigmin[chi] - median[chi] > 0.0) {
if (!btn[chi]) {
#ifdef DEBUG_PLOT_TRIGGERS
sp("Trig-"); sp(chi); spt(":5");
sprinted=true;
#endif
btn[chi] = bmillis;
} else if (btn[chi] == ULONG_MAX) { // waiting for release
#ifdef DEBUG_PLOT_TRIGGERS
sp("Trig-"); sp(chi); spt(":20");
sprinted=true;
#endif
} else if (bmillis - btn[chi] > 10) {
#ifdef DEBUG_PLOT_TRIGGERS
sp("Trig-"); sp(chi); spt(":10");
sp("ms:"); spt(bmillis-btn[chi]);
sprinted=true;
#endif
if (!chi) sendbutton=1;
else sendbutton=2;
btn[chi] = ULONG_MAX;
}
} else {
if (btn[chi] > 0) { // handles reset (ULONG_MAX) or millis
#ifdef DEBUG_PLOT_TRIGGERS
sp("Trig-"); sp(chi); spt(":0");
sprinted=true;
#endif
btn[chi] = 0;
}
}
en_print_ms = millis();
#if defined(DEBUG_PLOT_TRIGGERS) || defined(DEBUG_PLOT_TRIGGERS_ALLDATA)
/* sp("us:"); spt(en_print_ms - st_read_ms); */
if (sprinted) { spl(""); }
#endif
if (sendbutton==1) netdata_send_btn1();
else if (sendbutton==2) netdata_send_btn2();
}
/* #define PLOT */
#ifdef PLOT
if (cmillis-last_print_ms > 2) {
/* sp("us:"); spt(cmicros - last_proc_us); */
/* for (int chi=0; chi<1; chi++) { */
for (int chi=0; chi<SENCNT; chi++) {
for (int i=0; i<BUFCNT; i+=3) {
/* sp("v"); sp(chi); sp(':'); spt(bufv[chi][i]); */
sp("m"); sp(chi); sp(':'); spft(median[chi], 3);
/* sp("s"); sp(chi); sp(':'); spft(slv[chi], 3); */
/* sp("s2-"); sp(chi); sp(':'); spft(slv2[chi], 3); */
/* sp("s3-"); sp(chi); sp(':'); spft(slv3[0], 3); */
/* sp("mn"); sp(chi); sp(":"); spft(curmin[0], 3); */
/* sp("mx"); sp(chi); sp(":"); spft(curmax[0], 3); */
/* sp("slmn"); sp(chi); sp(":"); spft(slcurmin[0], 3); */
/* sp("slmx"); sp(chi); sp(":"); spft(slcurmax[0], 3); */
sp("trmn"); sp(chi); sp(':'); spft(trigmin[chi], 3);
sp("trmx"); sp(chi); sp(':'); spft(trigmax[chi], 3);
spl("");
}
}
last_print_ms = cmillis;
}
#endif
/* static UL last_btn=0; */
/* if (cmillis-last_btn > 1000) { */
/* netdata_send_btn1(); */
/* last_btn = cmillis; */
/* } */
last_proc_us = cmicros;
state = ST_READING;
}
if (cmillis - last_wifi_ms > 20) {
loop_ota();
loop_wifi();
loop_netdata();
last_wifi_ms = cmillis;
}
last_cmillis = cmillis;
return;
}
#ifndef _NETDATA_SETTINGS_H
#define _NETDATA_SETTINGS_H
// ***********************
// ** IMPORTANT
// ***********************
// You need to #define NETDATA_SETTINGS_MAIN at least
// in one place that's including this file, or otherwise
// declare those two char [] arrays: stmag and enmag
// This file is for setting your network MAGIC Sequences
// for the starts/ends of data bundles
// See MAGIC_ST, MAGIC_EN, etc.
// Define this in the .c where you want variables to be declared
// (Before including this .h)
// (Ie. do not define in other .c files so the variables
// end up being externs)
// Example: #define NETDATA_SETTINGS_MAIN
// You can see, below, the externs
//#define MAGICBUF_TEST
// Slow down how often we test for TCP
// (and the reconnections)
#define US_NETDATA_TEST 2000000
#define NET_MAXLEN 1000 // Ideally, the max packet size before your
// MCU will fail on them
// 'Magic' start/end sequences surrounding sensor bundles
// * array versions are used so sizeof() works directly
// * string versions are included mostly only for tests
// where you might want to concatenate them (see bottom of
// magicbuf.c)
#ifndef MAGICBUF_TEST
#define MAGIC_ST { 0375, 003, 0374 } // start packet bundle magic
#define MAGIC_EN { 0371, 004, 0372 } // end
#define MAGIC_ST_STR "\375\003\374" // Some might like to use this
#define MAGIC_EN_STR "\371\004\372" // in string concatenation
// ^ but otherwise the _STR versions are only used in the magicbuf
// test main() routine, and aren't needed unless you use them somewhere
#else
#define MAGIC_ST { 0101, 0132, 0102 } // start packet bundle magic
#define MAGIC_EN { 0104, 0131, 0103 } // end
//#define MAGIC_ST_STR "AZB" // Some might like to use this
//#define MAGIC_EN_STR "DYC" // in string concatenation
// ^ but otherwise the _STR versions are only used in the magicbuf
// test main() routine, and aren't needed unless you use them somewhere
#endif
#ifdef NETDATA_SETTINGS_MAIN
uint8_t stmag[]=MAGIC_ST;
uint8_t enmag[]=MAGIC_EN;
#else
extern uint8_t stmag[];
extern uint8_t enmag[];
#endif
//static_assert(sizeof(stmag)!= sizeof(enmag), "Let's keep MAGIC_ST and MAGIC_EN the same length");
//static_assert(sizeof((uint8_t[])MAGIC_ST) != sizeof((uint8_t[])MAGIC_ST), "Let's keep MAGIC_ST and MAGIC_EN the same length");
#define MAGIC_SIZE sizeof((uint8_t [])MAGIC_ST)
// Additional FULL net package info
// Must match client .ino
#define SAMPLE_SIZE (4+2)
#define PAKTYPE_SIZE 1
#define PAKTYPE_TYPE uint8_t
// packet/bundle types:
#define PAK_T_DATA 1
#define PAK_T_BTN1 2
#define PAK_T_BTN2 3
// Button
#define BTNPAK_SIZE (MAGIC_SIZE*2 + PAKTYPE_SIZE)
// For streaming data:
/* #define MAX_PACKETS (NET_MAXLEN/SAMPLE_SIZE) // fit within ESP's packet (524?) */
// For individual single-packet events like buttons
#define MAX_PACKETS 1
// Main data
#define FULLPAK_SIZE (MAGIC_SIZE*2 + PAKTYPE_SIZE + SAMPLE_SIZE*MAX_PACKETS)
// ^ this isn't fully accurate, if we were precise with the NET_MAXLEN,
// since we don't include the magic and stuff
#define PAKFULL_MAGIC_OFFSET (0) // start of buffer
#define PAKFULL_TYPE_OFFSET (MAGIC_SIZE) // right after magic
#define PAKFULL_DATA_OFFSET (MAGIC_SIZE + PAKTYPE_SIZE) // after magic and type
// ^ this is how far into the network package.. where the sensor data begins
#endif // _NETDATA_SETTINGS_H
#include <ctype.h>
#define _IN_NETDATA_C
#include "netdata.h"
#define NETDATA_SETTINGS_MAIN // declares char[] stmag and enmag
#include "netdata-settings.h"
#include "wifi_config.h"
#include "wifi.h"
#include "serialize.h"
#include "printutils.h"
WiFiClient server;
unsigned long us_last_nettest=micros();
// Full package to send out to net
// Includes: start and end MAGIC
// package type
// data
uint8_t ecg_fullpackage[FULLPAK_SIZE+1]; // +1 for safety. it's unused.
// \/ Points to where the data actually starts
uint8_t *ecg_netdata = ecg_fullpackage + MAGIC_SIZE + PAKTYPE_SIZE;
int nextpacketi=0;
// Full button package
struct ecg_btn1_package {
uint8_t magic_st[MAGIC_SIZE] = MAGIC_ST;
PAKTYPE_TYPE paktype[PAKTYPE_SIZE] = { PAK_T_BTN1 };
uint8_t magic_en[MAGIC_SIZE] = MAGIC_EN;
} ecg_btn1_package;
struct ecg_btn2_package {
uint8_t magic_st[MAGIC_SIZE] = MAGIC_ST;
PAKTYPE_TYPE paktype[PAKTYPE_SIZE] = { PAK_T_BTN2 };
uint8_t magic_en[MAGIC_SIZE] = MAGIC_EN;
} ecg_btn2_package;
void setup_netdata() {
static_assert(sizeof(stmag) == sizeof(enmag), "Let's keep MAGIC_ST and MAGIC_EN the same length");
static_assert(PAKTYPE_SIZE == 1, "PAKTYPE_SIZE should be 1, or you'll need to modify the data sending to encode it for the network");
}
void netdata_add(uint16_t v) { // call to add value to send
/* packets[nextpacketi].us = micros(); */
/* packets[nextpacketi].val = v; */
// void packi16(unsigned char *buf, unsigned int i)
// void packi32(unsigned char *buf, unsigned long int i)
uint32_t us;
uint16_t testval;
/* #warning "netdata_add() is disabled" */
/* return; */
//us = micros();
us = millis();
/* us = *((uint32_t *)"abcd"); */
/* v = *((uint16_t *)"yz"); */
/* us = 123456; */
/* v = 45678; */
packi32(ecg_netdata + (nextpacketi*SAMPLE_SIZE), us);
packi16(ecg_netdata + (nextpacketi*SAMPLE_SIZE) + 4, v);
/* dbsp(" u:"); */
/* dbsp(packets[nextpacketi].us); */
/* dbsp(" v:"); */
/* dbsp(packets[nextpacketi].val); */
/* dbsp(". "); */
nextpacketi++;
if (nextpacketi >= MAX_PACKETS) {
netdata_send();
nextpacketi=0;
}
}
void netdata_send_btn1() {
#warning "server.connected() might be unreliable. Disabling for now."
if (!server.connected()) {
spl(F("TCP not connected. Button not sent"));
} else {
/* server.write((uint8_t *)(&ecg_btn1_package), BTNPAK_SIZE); */
spl("Sending <b1-1>");
int rc=server.write("<b1-1>", 5);
server.flush();
sp(F("BTN1 sent ("));
sp(rc);
spl(F(" bytes)"));
}
}
void netdata_send_btn2() {
if (0 && !server.connected()) {
spl(F("TCP not connected. Button not sent"));
} else {
spl("Sending <b2-1>");
/* server.write((uint8_t *)(&ecg_btn2_package), BTNPAK_SIZE); */
int rc=server.write("<b2-1>", 5);
server.flush();
sp(F("BTN2 sent ("));
sp(rc);
spl(F(" bytes)"));
}
}
void netdata_send() {
#warning "We're not presently using netdata_send()"
return;
if (!server.connected()) {
// don't bother sending out msg if wifi's down, since it
// should already be complaining through serial:
spl(F("TCP not connected. Losing data"));
} else {
spl(F("netadata_send() called. Not sure why; we're only doing events."));
return;
/* dbsp("[>"); */
/* dbsp(PACKETCNT); */
/* dbsp("="); */
/* dbsp(sizeof(packets)); */
/* dbsp("b "); */
memcpy(ecg_fullpackage + PAKFULL_MAGIC_OFFSET, stmag, MAGIC_SIZE);
// \/ we static_assert()ed that this is one byte:
ecg_fullpackage[PAKFULL_TYPE_OFFSET] = PAK_T_DATA;
//memcpy(ecg_fullpackage + PAKFULL_DATA_OFFSET, stmag, sizeof(stmag));
// ^ data should already be in place from ecg_netdata pointing there
// \/ here we have to add magic to the end:
memcpy(ecg_fullpackage + PAKFULL_DATA_OFFSET + (nextpacketi*SAMPLE_SIZE),
enmag, MAGIC_SIZE);
/* No longer do as separate writes:
server.write(stmag, sizeof(stmag));
server.write(ecg_netdata, sizeof(ecg_netdata));
server.write(enmag, sizeof(enmag)); */
server.write(ecg_fullpackage,
PAKFULL_DATA_OFFSET + (nextpacketi*SAMPLE_SIZE) + MAGIC_SIZE);
/* dbspl(""); */
dbsp("Data size: ");
dbspl(PAKFULL_DATA_OFFSET + (nextpacketi*SAMPLE_SIZE) + MAGIC_SIZE);
//dbspl(sizeof(ecg_netdata) + sizeof(stmag) + sizeof(enmag));
//dbspl("");
}
}
void netdata_server_reconnect_test() {
unsigned long us_cur = micros();
if (us_cur - us_last_nettest > US_NETDATA_TEST) {
us_last_nettest = us_cur;
if (!server.connected()) {
spl("TCP Connecting...");
if (server.connect(DATA_HOST, DATA_PORT)) {
spl(" TCP Connected! Logging in...");
int rc = server.write("login 123456\n", 13);
sp(" TCP Hopefully login worked, but we're moving on now... (Wrote ");
sp(rc);
spl(" bytes)");
server.setNoDelay(true);
}
spl("/TCP Connecting");
} else {
}
}
}
void loop_netdata() {
if (!(wifi_connflags & WIFI_FLAG_CONNECTED)) { // only bother if wifi connected
spl("WIFI not connected");
} else {
/* netdata_server_reconnect_test(); */
}
}
#ifndef _NETDATA_H
#define _NETDATA_H
#include <stdint.h> // for uint8_t etc.
#include <assert.h> // for static_assert(), for sizeof() in #if
void setup_netdata(); // once in setup()
void loop_netdata(); // each loop() probably.. maybe.
void netdata_add(uint16_t v); // call to add value to send
void netdata_send();
void netdata_send_btn1();
void netdata_send_btn2();
void netdata_server_reconnect_test();
#endif // _NETDATA_H
#include <WiFi.h>
/* #include <Arduino.h> */
/* #include <WiFiGeneric.h> */
#include <WiFiClient.h>
#define PLOT_TO_SERIAL
#define WIFI_CONFIG_GET_IPS
#define __WIFI_CPP
#include "wifi_config.h"
#define _IN_WIFI_CPP
#include "wifi.h"
#include "printutils.h"
#include "netdata.h"
uint16_t wifi_connflags = 0;
/* WiFiEventHandler wifiConnectHandler; */
/* WiFiEventHandler wifiDisconnectHandler; */
/* WiFiEventHandler wifiGotIPHandler; */
void loop_wifi(void) {
/* long rssi = WiFi.RSSI(); */
/* unsigned long cur_millis = millis(); */
/* static unsigned long last_wifi_strength = cur_millis; */
/* if (cur_millis - last_wifi_strength > 500) { */
/* last_wifi_strength = cur_millis; */
/* sp("WiFi strength: "); */
/* spl(rssi); */
/* } */
}
void setup_wifi(void) {
WiFi.mode(WIFI_STA);
WiFi.config(ip, gw, nm);
/* WiFi.setOutputPower(20.5); // 0 - 20.5 (multiples of .25) */
spl(F("Connecting to wife (WiFi.begin())..."));
WiFi.onEvent(onWifiConnect, ARDUINO_EVENT_WIFI_STA_CONNECTED);
WiFi.onEvent(onWifiDisconnect, ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
WiFi.onEvent(onWifiGotIP, ARDUINO_EVENT_WIFI_STA_GOT_IP);
WiFi.setAutoReconnect(true);
WiFi.persistent(true); // reconnect to prior access point
WiFi.begin(ssid, password);
spl(F("We're also going to wait until WL_CONNECTED"));
/* while (WiFi.waitForConnectResult() != WL_CONNECTED) { */
/* //spl(F("Conn. fail! Rebooting...")); */
/* delay(500); */
/* spl(F("Conn. fail!")); */
/* //ESP.restart(); */
/* } */
WiFi.setAutoReconnect(true);
WiFi.persistent(true); // reconnect to prior access point
wifi_connflags = WIFI_FLAG_CONNECTED;
}
void onWifiGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
spl(F("EVENT: IP established sucessfully."));
sp(F("IP address: "));
spl(WiFi.localIP());
wifi_connflags = WIFI_FLAG_CONNECTED;
}
void onWifiDisconnect(WiFiEvent_t event, WiFiEventInfo_t info) {
spl(F("EVENT: Disconnected from Wi-Fi. Auto-reconnect should happen."));
/* WiFi.disconnect(); */
/* WiFi.begin(ssid, password); */
wifi_connflags = 0;
}
void onWifiConnect(WiFiEvent_t event, WiFiEventInfo_t info) {
long rssi = WiFi.RSSI();
sp(F("EVENT: Connected to Wi-Fi sucessfully. Strength: "));
spl(rssi);
spl("Connecting to TCP server...");
netdata_server_reconnect_test();
}
// Optional call to use if trying to requiring wifi during setup()
// Wait max of passed seconds for wifi
// Returns flags immediately upon success (eg. WIFI_FLAG_CONNECTED)
// Return flags of 0 means NOT connected for timeout period
uint16_t setup_wait_wifi(unsigned int timeout_s) {
unsigned long mil = millis();
bool ret;
while (((millis() - mil)/1000) < timeout_s) {
ret = loop_check_wifi(); // after 3s this fn will start printing to serial
if (ret) return ret;
delay(99);
}
return 0;
}
uint16_t loop_check_wifi() {
static int connected=false;
unsigned long cur_millis = millis();
static unsigned long last_wifi_millis = cur_millis;
/* static unsigned long last_connect_millis = 0; */
static unsigned long last_reconnect_millis = 0;
if (cur_millis - last_wifi_millis < 2000) {
return WIFI_FLAG_IGNORE;
} else {
last_wifi_millis = cur_millis;
if (WiFi.status() == WL_CONNECTED) {
if (!connected) { // only if we toggled state
connected = true;
/* last_connect_millis = cur_millis; */
sp(F("Just connected to "));
sp(ssid);
sp(F(". IP: "));
spl(WiFi.localIP());
WiFi.setAutoReconnect(true);
WiFi.persistent(true); // reconnect to prior access point
return (WIFI_FLAG_CONNECTED | WIFI_FLAG_RECONNECTED);
} else {
return WIFI_FLAG_CONNECTED;
}
} else {
if (!connected) {
#ifndef PLOT_TO_SERIAL
sp(F("Not connected to wifi. millis="));
sp(cur_millis);
sp(F(", cur-last="));
spl(cur_millis - last_wifi_millis);
#endif
if (cur_millis - last_reconnect_millis > MAX_MS_BEFORE_RECONNECT) {
#ifndef PLOT_TO_SERIAL
spl(F(" Not connected to WiFi. Reconnecting (disabled)"));
#endif
last_reconnect_millis = cur_millis;
// WiFi.reconnect();
}
} else { // only if we toggled state
connected=false;
spl(F("Lost WiFi connection. Will try again."));
}
}
}
return 0; // not connected
}
#ifndef __WIFI_CONFIG_H
#define __WIFI_CONFIG_H
#include <ESP8266WiFi.h>
#define MDNS_NAME "LanDevice"
#define SSID_NAME "YourSSID"
#define SSID_PW "YourPASSWORD"
// The below might not be implemented
#define WEBUPDATE_USER "webuser"
#define WEBUPDATE_PW "webpw"
#define MAX_MS_BEFORE_RECONNECT 4500
// Server to connect to for logging
// (this is not our MCU IP. That's below.)
#define DATA_HOST "192.168.1.4"
#define DATA_ARDUINO_IP (192,168,1,4)
#define DATA_PORT 1234
#define DATA_PATH "/"
#ifdef __WIFI_CPP
const char *ssid = SSID_NAME;
//#define SSPW {33+22, 3, 62+22, 4+2, 6+129, 0}
char password[] = SSID_PW;
const char *update_user = WEBUPDATE_USER; // HTTP auth user for OTA http update
const char *update_pw = WEBUPDATE_PW"; // HTTP auth password
#else // like: ifndef __MAIN_INO__
extern const char *ssid;
extern char password[];
extern const char *update_user; // HTTP auth user for OTA http update
extern const char *update_pw; // HTTP auth password
#endif
#ifdef WIFI_CONFIG_GET_IPS
IPAddress ip(192, 168, 1, 14);
IPAddress gw(192, 168, 1, 1);
IPAddress nm(255, 255, 255, 0);
#endif
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment