Skip to content
Brian Smith edited this page Mar 11, 2020 · 37 revisions

SensESP is a library of functions that makes it relatively simple to create a program that will run on an ESP8266 microcontroller ("MCU"), that collects data from various sensors, processes the data, and sends it along to a final "consumer", typically a Signal K server. It must be used with the PlatformIO IDE - it won't work with the Arduino IDE.

As the end user, you create a single main.cpp file, most of which will be boilerplate - all the code necessary to connect to your network and your SignalK server. Then, with only a few lines of code, you create an instance of a sensor, process the data from the sensor, then send the final result to the Signal K server.

The best way to learn how to use SensESP is by looking at a few examples. In the /examples folder, rpm_counter.cpp is a good one to start with, as it illustrates a simple implementation - reading the value of a sensor connected to a GPIO pin on the MCU, converting that value to hertz (the native unit of measurement for a tachometer in Signal K), then sending the value in hertz to the Signal K server.

Transports

A Transport is an object that takes a value as input (from a Sensor, or from another Transport), does something with that value, then outputs the new value, either to another Transport, or to the Signal K server. In the rpm_counter.cpp example referred to above, the meat of the code is these three lines:

     auto* pSensor = new DigitalInputCounter(D5, INPUT_PULLUP, RISING, read_delay);
     
     pSensor->connectTo(new Frequency(multiplier, config_path_calibrate))
            ->connectTo(new SKOutputNumber(sk_path, config_path_skpath));

The first line instantiates a Sensor of type DigitalInputCounter. The second line is a Transport of type Frequency - it takes a raw number from the DigitalInputCounter Sensor and converts it to hertz, then passes it along to SKOutputNumber. SKOutputNumber is a special Transport whose purpose is to send a value to the Signal K server.

A much more complex example is temperature_sender.cpp, where the meat of the program is this:

auto* pAnalogInput = new AnalogInput();

pAnalogInput->connectTo(new AnalogVoltage()) -> 
              connectTo(new VoltageDividerR2(R1, Vin, "/gen/temp/sender")) -> 
              connectTo(new TemperatureInterpreter("/gen/temp/curve")) -> 
              connectTo(new Linear(1.0, 0.0, "/gen/temp/calibrate")) -> 
              connectTo(new SKOutputNumber(sk_path, "/gen/temp/sk"));

In this example, there is still only one Sensor (AnalogInput), but several Transports, all required to turn the raw value from the Analog Input pin on the MCU into a temperature that's sent to the Signal K server.

You can also include multiple Sensors, each with at least one Transport, in the same program, such as combining both of the examples above into the same main.cpp, one after the other. (TODO - add such an example to /examples.)

Configuration Paths

Some Sensors and Transports have parameters that can be configured "live", by accessing the MCU through its IP address, entered as a URL in any browser. For example, entering 192.168.1.236 (the IP address of the MCU I'm currently using as my example) in a browser will bring up the following web page that's hosted by the MCU itself:

image

"Device information" does not display any information at this time. "Configure device" will be explained below. "Restart device" will restart the MCU. "Reset device" will erase all the network information and all the Sensor and Transport configuration, and the program. The MCU will be returned to the way it came from the factory.

Click on "Configure device" to bring up the /setup page, which will look something like this: image

The only menu item that will always be present is "system", which has two sub-menus: "networking" (which lets you see and edit your wifi SSID and password, and the MCU's hostname), and "sk", which displays some networking info, but can't yet be used for editing that info, although it looks like it can.

The other menu items ("sensors" and "transports") are there only if you've provided a configuration path in the constructor of one or more of the Sensors and Transports in main.cpp. And the names - in this case, "sensors" and "transports", are completely up to you - you can call them "fred" and "barney" if you like.

Look at the three lines from the rpm_counter.cpp example above. There are three constructors - the one for the DigitalInputCounter Sensor, the one for the Frequency Transport, and the one for the SKOutputNumber Transport. The latter two have a configuration path included as the last item in their parameter list, but the first one doesn't. That means that the first one - the DigitalInputCounter - has no values that can be configured "live", but the latter two do. Actually, it's a little more complicated than that, because it's not entirely consistent among all Sensors and Transports.

As of this writing (March 2020), here are the ** possible ** configurable parameters for each Sensor and Transport:

SENSORS

  • AnalogInput: Read delay (Number of milliseconds between each analogRead(A0))
  • DigitalInputValue: none
  • DigitalInputCounter: Read delay (The time, in milliseconds, between each read of the input) GPSInput: none OneWireTemperature: OneWire address (the unique address of the specific sensor being used)

TRANSFORMS

AnalogVoltage: none AngleCorrection: Constant offset (value to be added, in radians); Minimum angle value (pi, or 0) ChangeFilter: Minimum delta (Minimum difference in change of value before forwarding); Maximum delta (maximum difference in change of value to allow forwarding); Max skips (maximum number of consecutive filtered values before one is allowed through) CurveInterpolator: input, output (each pair is added to the table of samples) Difference: Input #1 multiplier, Input #2 multiplier Frequency: Multiplier Integrator: Multiplier Linear: Multiplier; Constant offset Median: Sample size (number of samples to take before outputing a value) MovingAverage: Number of samples in average; Multiplier VoltageDivider: Voltage in; Resistance (ohms) of R1 SKOutputNumber, SKOutputInt, SKOutputBool, SKOutputString: Signal K data path

Clone this wiki locally