Skip to content

Configuration

Sensors and Peripherals

You can add up to 3 user defined sensors. Insert your sensor's payload scheme in sensor.cpp. More examples and a detailed description can be found in the sensor documentation.

Supported Peripherals

  • Bosch BMP180 / BME280 / BMP280 / BMP680
  • SDS011
  • RTC DS3231
  • generic serial NMEA GPS
  • I2C Lopy GPS

For these peripherals no additional code is needed. To activate configure them in the board's hal file before building the code.

See generic.h for all options and for proper configuration of BME280/BME680.

shared/hal/generic.h
// BME680 sensor on I2C bus
//#define HAS_BME 1 // Enable BME sensors in general
//#define HAS_BME680 GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL
//#define BME680_ADDR BME68X_I2C_ADDR_LOW // connect SDIO of BME680 to GND

// BME280 sensor on I2C bus
//#define HAS_BME 1 // Enable BME sensors in general
//#define HAS_BME280 GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL
//#define BME280_ADDR 0x76 // change to 0x77 depending on your wiring

// BMP180 sensor on I2C bus
//#define HAS_BME 1 // Enable BME sensors in general
//#define HAS_BMP180
//#define BMP180_ADDR 0x77

// BMP280 sensor on I2C bus
//#define HAS_BME 1 // Enable BME sensors in general
//#define HAS_BMP280
//#define BMP280_ADDR 0x76
shared/hal/generic.h
// SDS011 dust sensor settings
//#define HAS_SDS011 1 // use SDS011
// used pins on the ESP-side:
//#define SDS_TX 19     // connect to RX on the SDS011
//#define SDS_RX 23     // connect to TX on the SDS011
shared/hal/generic.h
// up to three user defined sensors (if connected)
//#define HAS_SENSOR_1 1 // comment out if device has user defined sensor #1
//#define HAS_SENSOR_2 1 // comment out if device has user defined sensor #2
//#define HAS_SENSOR_3 1 // comment out if device has user defined sensor #3
shared/hal/generic.h
// clang-format off
// upload_speed 115200
// board esp32dev

#ifndef _GENERIC_H
#define _GENERIC_H

#include <stdint.h>

// Hardware related definitions for generic ESP32 boards
// generic.h is kitchensink with all available options

#define HAS_LORA 1 // comment out if device shall not send data via LoRa or has no LoRa
//#define HAS_SPI 1  // comment out if device shall not send data via SPI
// pin definitions for SPI slave interface
//#define SPI_MOSI GPIO_NUM_23
//#define SPI_MISO GPIO_NUM_19
//#define SPI_SCLK GPIO_NUM_18
//#define SPI_CS   GPIO_NUM_5

// enable only if you want to store a local paxcount table on the device
#define HAS_SDCARD  1      // this board has an SD-card-reader/writer
// Pins for SD-card
#define SDCARD_CS    (13)
#define SDCARD_MOSI  (15)
#define SDCARD_MISO  (2)
#define SDCARD_SCLK  (14)

// enable only if device has these sensors, otherwise comment these lines
// tutorial to connect BME sensor see here:
// https://sbamueller.wordpress.com/2019/02/26/paxcounter-mit-umweltsensor/
//
// in platformio.ini append
// lib_deps = <...> ${common.lib_deps_sensors}
// for loading necessary libraries

// BME680 sensor on I2C bus
//#define HAS_BME 1 // Enable BME sensors in general
//#define HAS_BME680 GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL
//#define BME680_ADDR BME68X_I2C_ADDR_LOW // connect SDIO of BME680 to GND

// BME280 sensor on I2C bus
//#define HAS_BME 1 // Enable BME sensors in general
//#define HAS_BME280 GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL
//#define BME280_ADDR 0x76 // change to 0x77 depending on your wiring

// BMP180 sensor on I2C bus
//#define HAS_BME 1 // Enable BME sensors in general
//#define HAS_BMP180
//#define BMP180_ADDR 0x77

// BMP280 sensor on I2C bus
//#define HAS_BME 1 // Enable BME sensors in general
//#define HAS_BMP280
//#define BMP280_ADDR 0x76

// SDS011 dust sensor settings
//#define HAS_SDS011 1 // use SDS011
// used pins on the ESP-side:
//#define SDS_TX 19     // connect to RX on the SDS011
//#define SDS_RX 23     // connect to TX on the SDS011

// up to three user defined sensors (if connected)
//#define HAS_SENSOR_1 1 // comment out if device has user defined sensor #1
//#define HAS_SENSOR_2 1 // comment out if device has user defined sensor #2
//#define HAS_SENSOR_3 1 // comment out if device has user defined sensor #3

#define CFG_sx1276_radio 1 // select LoRa chip
//#define CFG_sx1272_radio 1 // select LoRa chip
//#define BOARD_HAS_PSRAM // use if board has external SPIRAM, note: this will reduce IRAM0 by 64KB for SPIRAM cache
#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature

//#define HAS_DISPLAY 1
//#define MY_DISPLAY_FLIP  1 // use if display is rotated
#define BAT_MEASURE_ADC ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7
#define BAT_VOLTAGE_DIVIDER 2 // voltage divider 100k/100k on board

#define HAS_LED (21) // on board  LED
#define HAS_BUTTON (39) // on board button
//#define RGB_LED_COUNT 1 // we have 1 LED
//#define HAS_RGB_LED FastLED.addLeds<WS2812, GPIO_NUM_0, GRB>(leds, RGB_LED_COUNT);

// GPS settings
//#define HAS_GPS 1 // use on board GPS
//#define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_12, GPIO_NUM_15 // UBlox NEO 6M RX, TX
//#define GPS_INT GPIO_NUM_13 // 30ns accurary timepulse, to be external wired on pcb: NEO 6M Pin#3 -> GPIO13

// Pins for I2C interface of OLED Display
//#define MY_DISPLAY_SDA (4)
//#define MY_DISPLAY_SCL (15)
//#define MY_DISPLAY_RST (16)

// Settings for on board DS3231 RTC chip
//#define HAS_RTC MY_DISPLAY_SDA, MY_DISPLAY_SCL // SDA, SCL
//#define RTC_INT GPIO_NUM_34 // timepulse with accuracy +/- 2*e-6 [microseconds] = 0,1728sec / day

// Settings for IF482 interface
//#define HAS_IF482 9600, SERIAL_7E1, GPIO_NUM_12, GPIO_NUM_14 // IF482 serial port parameters

// Settings for DCF77 interface
//#define HAS_DCF77 GPIO_NUM_1
//#define DCF77_ACTIVE_LOW 1

// Pins for LORA chip SPI interface, reset line and interrupt lines
#define LORA_SCK  (5) 
#define LORA_CS   (18)
#define LORA_MISO (19)
#define LORA_MOSI (27)
#define LORA_RST  (14)
#define LORA_IRQ  (26)
#define LORA_IO1  (33)
#define LORA_IO2  LMIC_UNUSED_PIN

#endif

Output of user sensor data can be switched by user remote control command 0x14 sent to Port 2.

Output of sensor and peripheral data is internally switched by a bitmask register. Default mask can be tailored by editing cfg.payloadmask initialization value in configmanager.cpp following this scheme:

Bit Sensordata Default
0 Paxcounter on
1 unused off
2 BME280/680 on
3 GPS* on
4 User sensor 1 on
5 User sensor 2 on
6 User sensor 3 on
7 Batterylevel off

*) GPS data can also be combined with paxcounter payload on port 1, #define GPSPORT 1 in paxcounter.conf to enable

shared/paxcounter_orig.conf
#define GPSPORT                         4       // gps - NOTE: set to 1 to send combined GPS+COUNTERPORT payload

Power saving mode

Paxcounter supports a battery friendly power saving mode. In this mode the device enters deep sleep, after all data is polled from all sensors and the dataset is completeley sent through all user configured channels (LORAWAN / SPI / MQTT / SD-Card). Set #define SLEEPCYCLE in paxcounter.conf to enable power saving mode and to specify the duration of a sleep cycle.

shared/paxcounter_orig.conf
#define SLEEPCYCLE                      0       // sleep time after a send cycle [seconds/10], 0 .. 65535; 0 means no sleep [default = 0]

Power consumption in deep sleep mode depends on your hardware, i.e. if on board peripherals can be switched off or set to a chip specific sleep mode either by MCU or by power management unit (PMU) as found on TTGO T-BEAM v1.0/V1.1. See power.cpp for power management, and reset.cpp for sleep and wakeup logic.

Time sync

Paxcounter can keep a time-of-day synced with external or on board time sources. Set #define TIME_SYNC_INTERVAL in paxcounter.conf to enable time sync.

shared/paxcounter_orig.conf
#define TIME_SYNC_INTERVAL              60      // sync time attempt each .. minutes from time source [default = 60], 0 means off

Supported external time sources are GPS, LORAWAN network time and LORAWAN application timeserver time. Supported on board time sources are the RTC of ESP32 and a DS3231 RTC chip, both are kept sycned as fallback time sources. Time accuracy depends on board's time base which generates the pulse per second. Supported are GPS PPS, SQW output of RTC, and internal ESP32 hardware timer. Time base is selected by #defines in the board's hal file, see example in generic.h.

shared/hal/generic.h
// Settings for on board DS3231 RTC chip
//#define HAS_RTC MY_DISPLAY_SDA, MY_DISPLAY_SCL // SDA, SCL
//#define RTC_INT GPIO_NUM_34 // timepulse with accuracy +/- 2*e-6 [microseconds] = 0,1728sec / day

Tip

If your LORAWAN network does not support network time, you can run a Node-Red timeserver application using the enclosed Timeserver code. Configure the MQTT nodes in Node-Red for the LORAWAN application used by your paxcounter device. Time can also be set without precision liability, by simple remote command, see section remote control.

Syncing multiple paxcounters

A fleet of paxcounters can be synchronized to keep all devices wake up and start scanning at the same time. Synchronization is based on top-of-hour as common time point of reference. This feature requires time-of-day to be present on each device. Thus, TIME_SYNC_INTERVAL option, as explained above, must be enabled. Wake up syncing is enabled by setting SYNCWAKEUP in paxcounter.conf to a value X, in seconds, greater than zero, and smaller than SLEEPCYCLE (in seconds/10). This defines a time window, centered at top-of-hour, sized +/- X seconds. If a device, returning from sleep, would wakeup within this time window, it's wakeup will be adjusted to top-of-hour.

Wall clock controller

Paxcounter can be used to sync a wall clock which has a DCF77 or IF482 time telegram input. Set #define HAS_IF482 or #define HAS_DCF77 in board's hal file to setup clock controller. Use case of this function is to integrate paxcounter and clock. Accurary of the synthetic DCF77 signal depends on accuracy of on board's time base, see above.

Mobile PaxCounter using openSenseMap

This describes how to set up a mobile PaxCounter:
Follow all steps so far for preparing the device, selecting the packed payload format. In paxcounter.conf set PAYLOAD_OPENSENSEBOX to 1.

shared/paxcounter_orig.conf
#define PAYLOAD_OPENSENSEBOX            0       // send payload compatible to sensebox.de (swap geo position and pax data)

Register a new sensebox on https://opensensemap.org/. In the sensor configuration select "TheThingsNetwork" and set decoding profile to "LoRa serialization". Enter your TTN Application and Device ID. Setup decoding option using:

 [{"decoder":"latLng"},{"decoder":"uint16",sensor_id":"yoursensorid"}]

SD-card

Data can be stored on a FAT32 (pre-)formatted SD-card if the board provides an SD card interface, either with SPI or MMC mode. To enable this feature, specify interface mode and hardware pins in board's hal file (shared/hal/<board.h\>):

    #define HAS_SDCARD 1     // SD-card interface, using SPI mode
    //OR
    #define HAS_SDCARD 2     // SD-card interface, using MMC mode

    // Pins for SPI interface
    #define SDCARD_CS   (13) // fill in the correct numbers for your board
    #define SDCARD_MOSI (15)
    #define SDCARD_MISO (2)
    #define SDCARD_SCLK (14)

This is an example of a board with MMC SD-card interface: https://www.aliexpress.com/item/32915894264.html. For this board use file shared/hal/ttgov21new.h and add the lines given above.

Another approach would be this tiny board: https://www.aliexpress.com/item/32424558182.html (needs 5V). In this case you choose the correct file for your ESP32-board in the shared/hal-directory and add the lines given above. Edit the pin numbers given in the example, according to your wiring.

Data is written on SD-card to a single file. After 3 write operations the data is flushed to the disk to minimize flash write cycles. Thus, up to the last 3 records of data will get lost when the Paxcounter looses power during operation.

Format of the resulting file is CSV, thus easy import in LibreOffice, Excel, InfluxDB, etc. Each record contains timestamp (in ISO8601 format), paxcount (wifi and ble) and battery voltage (optional). Voltage is logged if the device has a battery voltage sensor (to be configured in board hal file).

File contents example:

    timestamp,wifi,ble[,voltage]
    2022-01-30T21:12:41Z,11,25[,4100]
    2022-01-30T21:14:24Z,10,21[,4070]
    2022-01-30T21:16:08Z,12,26[,4102]
    2022-01-30T21:17:52Z,11,26[,4076]
If you want to change this, modify src/sdcard.cpp and include/sdcard.h.

Additionally, it's possible to redirect system console output to a plain text file on SD card. This can be useful for debugging headless devices in the field. In paxcounter.conf set SDLOGGING to 1.

shared/paxcounter_orig.conf
#define SDLOGGING                       0       // set to 1 for system logging to SD card (if device has one)