Coder Social home page Coder Social logo

openslab-osu / loom-v4 Goto Github PK

View Code? Open in Web Editor NEW
7.0 3.0 1.0 4.99 MB

Open Source Internet Of Things Rapid Prototyping Framework For Environmental Sensing Applications

C++ 95.44% JavaScript 4.56%
arduino data-logging sensors environmental-monitoring

loom-v4's Introduction

logo

Loom Version 4

An Internet of Things Rapid Prototyping System for applications in environmental sensing
Documentation · Project Wiki · Quick Start

Table of Contents


Introduction

This version takes a step back and removes a lot of the aspects that make Loom 3 very hard to work with. This results in a more open and easy to work with framework that allows user to choose to use Loom and its features, or simply use the reliable software written for these sensors without the loom overarch.

Install

The install process is fairly simple:

Install Arduino

  • Download and install the latest version of the Arduino IDE

  • NOTE: If installing on Windows, download the Windows Installer

  • NOTE: If installing on Linux, see the official Linux install guide

Install Board Profiles

  1. Open Arduino IDE
  2. Once Open Click File > Preferences or Ctrl + ,
  3. In the text box labeled "Additional Boards Manager URLs" paste this text into the box https://adafruit.github.io/arduino-board-index/package_adafruit_index.json,https://raw.githubusercontent.com/OPEnSLab-OSU/Loom-V4/main/auxilary/package_loom4_index.json
  4. Press Ok
  5. Next click Tools > Board > Boards Manager
  6. Search and install the following Board Profiles
    • Arduino SAMD Boards
    • Adafruit SAMD Boards
    • Loom SAMD Boards V4
  7. Install the latest version of all three boards as they appear

If you use Mac:

Give Arduino IDE Full Disk Access: System Preferences->Security & Privacy->"Privacy" tab->Full Disk Access->+ plus button to add Arduino You will also need to install Developet Tools, which requires Admin access.

Getting Started Resources

  1. Loom Manager Walkthrough: https://media.oregonstate.edu/media/t/1_csq6zrae
  2. Loom Hypnos Walkthrough: https://media.oregonstate.edu/media/t/1_7owroc4a
  3. Hypnos Interrupts: https://media.oregonstate.edu/media/t/1_7hq18o2d
  4. C++ Tutorials https://www.cprogramming.com/tutorial/c++-tutorial.html?inl=nv
  5. Loom Sensor Hookup Tutorials: https://www.youtube.com/watch?v=AU5vwO4RJqE&list=PLGLI7V_o5-ahvLrscgoZRVfLx5KtgjEVV&index=3
  6. How to use Git: https://youtu.be/jRJ6Aklc4iQ
  7. Loom Logger: https://youtu.be/O3mnjWIp8MI
  8. I2C and I2C: https://youtu.be/TrAzs9ex4kE

Run an Example

Select Board

  • Make sure in the Tools > Board menu, that "Loomified Feather M0" is selected
    • If that board is not present, make sure you followed all the instructions above in Installation
    • Plug in your Feather board and then make sure in the Tools > Port menu that you select the device with "Adafruit Feather M0" in the name.

Compile

  • Start by compiling our Basic Loom examples (File > Examples > Loom > Sensors > Analog) to ensure that it compiles. If not, review the previous steps.
    • Once the Basic example is open, click the checkbox icon "Verify" in the top. (This may take several minutes to compile, this is to be expected)
    • You should get white-color font text readout mentioning a successful compilation and x% memory used. Successful compilation message
    • Note: may disregard orange-color warning text regarding nRF

Troubleshooting

If you get permissions error accessing the library folder, and are using a Mac, see note in the installation section above. If you are updating from an old version of Loom, you may need to do a "clean install" by removing the Arduino15 folder, and starting the process from the beginning to install again.

Issues

If you are experiencing issues, please click the "Issues" tab on this repo and choose the template that best fits your needs. Please supply as much information as possible. This helps us to better understand a fix issues quickly

Weird Feather M0 Issues

There are some weird idiosyncrasies with the Feather M0

  • Something that is only found in the datasheet is that pin A7 and pin D9 are linked together and since A7 is the voltage divider this pin sits at around 2v at all times

  • Some interrupt vectors are linked together so multiple pins may use the same interrupt and may then break interrupts below is a list of pins and their corresponding interrupt

    Pin # Interrupt #
    D11 0
    D13 1
    D10, A0, A5 2
    D12 3
    D6, A3 4
    A4 5
    SDA 6
    D9, SCL 7
    A1 8
    A2 9
    D23, D1 10
    D24, D0 11
    D5 15
  • LoRa Must Be Configured Properly based off the selected modem configuration, see issue: #54

  • Please DO NOT use the Arduino String library, if at all possible it fragments the crap out of the memory and makes devices crash. I spent ~40 hours or so porting the entire library to C-strings - Will

OPEnS Supported Projects

  • WeatherChimes (Stable ✅)
  • Lily Pad (Stable ✅)
  • FloDar (Stable ✅)
  • Smart Rock (Stable ✅)
  • Evaporometer (Stable ✅)
  • Dendrometer (Stable ✅)

loom-v4's People

Contributors

alexeiaburgos avatar drcrockerjr avatar hockerte avatar jamopopper avatar sahithreddy05 avatar sarvesh-thiruppathi avatar solidstatebird avatar sorenemmons avatar udellc avatar wl-richards avatar zakaryw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

ryanpcole

loom-v4's Issues

Loom Max, Access Point WiFi Mode

In Loom 4 Max, There are 2 ways to connect a device to the computer.
Client Mode: Loom device WiFi connects to a WiFi router with an SSID and Password.
Access Point (AP) Mode: Loom WiFi device acts as the access point and the computer connects to it, no password required.

AP mode is used in classes a lot as many devices cannot be run on client from a central router due to too much traffic.
AP Mode is a great start up state or default revert state if new router credentials need to be sent.

Can we make an example of the Loom MPU to work in AP Mode?
In Loom3 these were denoted as modes 7002 and 7003 or something like that. Arbitrary numbers to my understanding.

New low power library, logs only once after sleep on INT pin other than 12

Describe the bug
Standard Hypnos sleep interrupts on pin 12 seem okay so far. But when assigning the DS3231 in hardware to another pin, and setting the interrupt pin in software to that pin, it will only wake once after going to sleep.

Hardware in Use
Adalogger with external DS3231 RTC with INT pin on pin 10.
with function hypnos.registerInterrupt(isrTrigger, 10, SLEEP, LOW);

Expected behavior
Should function the same as if hardware were configured for pin 12
Code

/**
 * Log STEMMA soil moisture sensor to SD
 * 
 * MANAGER MUST BE INCLUDED FIRST IN ALL CODE
 */


#include <Loom_Manager.h>

#include <Hardware/Loom_Hypnos/Loom_Hypnos.h> // Loom Hypnos Library for SD and sleep functions
#include <Sensors/I2C/Loom_STEMMA/Loom_STEMMA.h> // STEMMA soil sensor library

// Create instance of Loom Manager
Manager manager("Device", 1); // Change name in quotes to name your device, no spaces

Loom_Hypnos hypnos(manager, HYPNOS_VERSION::ADALOGGER, TIME_ZONE::PST);

// Create Instance of STEMMA and associate with the manager
Loom_STEMMA stemma(manager);

// Called when the interrupt is triggered 
void isrTrigger(){
  hypnos.wakeup();
}

void setup() {
  delay(1000);
  // Start the serial interface and wait for the user to open the serial monitor
  manager.beginSerial();
  
  pinMode(LED_BUILTIN, OUTPUT);
  
  // Enable the hypnos functions
  hypnos.enable();

  // Initialize the manager
  manager.initialize();

  // Register the ISR and attach to the interrupt
  //hypnos.registerInterrupt(isrTrigger);
  hypnos.registerInterrupt(isrTrigger, 10, SLEEP, LOW);

}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH); 
  // Measure all sensors associated with Loom Manager
  manager.measure();

  // Package sensor data into JSON format
  manager.package();

  // Display JSON data on serial monitor if open
  manager.display_data();

  // Log JSON data to SD Card file
  // Filename is based on name and number given to manager on line 14
  hypnos.logToSD();

  // Set the RTC interrupt alarm to wake the device in 10 seconds
  hypnos.setInterruptDuration(TimeSpan(0, 0, 0, 10));

  // Reattach to the interrupt after we have set the alarm so we can have repeat triggers
  hypnos.reattachRTCInterrupt();

  digitalWrite(LED_BUILTIN, LOW);
  
  // Put the device into a deep sleep, operation HALTS here until the interrupt is triggered
  hypnos.sleep();
}

Output
[SD Manager] Initializing SD Card...
[SD Manager] Successfully initialized SD Card!
[SD Manager] Data will be logged to Device16.csv
[Hypnos] DS3231 Real-Time Clock Initialized Successfully!
[Manager] Initializing Modules...
[STEMMA] Successfully initialized STEMMA Version: 263858063
[Manager] ** Setup Complete **
[Hypnos] Registering interrupt on pin 10...

[Manager] Data Json:
{
"type": "data",
"id": {
"name": "Device",
"instance": 1
},
"contents": [
{
"module": "Packet",
"data": {
"Number": 1
}
},
{
"module": "STEMMA",
"data": {
"Temperature": 25.36451721,
"Capacitive": 434
}
}
],
"timestamp": {
"time_utc": "2022-09-10 7:31:9",
"time_local": "2022-09-10 0:31:9"
}
}

[SD Manager] Successfully logged data to Device16.csv
[Hypnos] Current Time: 2022.09.10 00:31:09
[Hypnos] Next Interrupt Alarm Set For: 2022.09.10 00:31:19
[Hypnos] Interrupt successfully reattached!
[Hypnos] Entering Standby Sleep...

Additional context
SD card has 2 samples logged. The first one before sleep from the printout above, and one more post-sleep. but no more than that after.

Fix Max examples typos

Max_MPU has typo in line 18 fails to compile
Loom_Max maxMsp(manager, wifi, );
should be
Loom_Max maxMsp(manager, wifi);

Go through all examples for compile confirmation

All examples need delay() functions at end of loop replaced with manager.pause()

Possible breaking change: 2 MS5803 sensors i2c

Pulled the main 9/30/22 at 4pm.
using two MS5803 sensors worked in version before in integration hell branch.
Possible changes to i2c NAK failing gracefully may have caused break in the two MS5803 0x118 snd 0x119 functionality.
Shows both MS5803s initializing, but only one reports, does not say which one.

Tested in Weatherchimes code below:

/**
 * In lab use case example for the WeatherChimes project
 * 
 * This project uses SDI12, TSL2591 and an SHT31 sensor to log environment data and logs it to both the SD card and also MQTT/MongoDB
 * 
 * MANAGER MUST BE INCLUDED FIRST IN ALL CODE
 */
#include "arduino_secrets.h"

#include <Loom_Manager.h>

#include <Hardware/Loom_Hypnos/Loom_Hypnos.h>

#include <Sensors/Loom_Analog/Loom_Analog.h>
#include <Sensors/I2C/Loom_SHT31/Loom_SHT31.h>
#include <Sensors/I2C/Loom_TSL2591/Loom_TSL2591.h>
#include <Sensors/I2C/Loom_MS5803/Loom_MS5803.h>
// If using Teros 10, Uncoment this line
#include <Sensors/Analog/Loom_Teros10/Loom_Teros10.h>

// If using SDI12, GS3 or Teros 11 or 12 uncoment this line
//#include <Sensors/SDI12/Loom_SDI12/Loom_SDI12.h>

#include <Internet/Logging/Loom_MQTT/Loom_MQTT.h>
#include <Internet/Connectivity/Loom_LTE/Loom_LTE.h>

Manager manager("4Gchime", 10);

// Create a new Hypnos object
Loom_Hypnos hypnos(manager, HYPNOS_VERSION::V3_3, TIME_ZONE::PST, true);
// Analog for reading battery voltage
Loom_Analog analog(manager);

// Create sensor classes
Loom_SHT31 sht(manager);
Loom_TSL2591 tsl(manager);
Loom_MS5803 ms_water(manager, 119); // 119(0x77) if CSB=LOW external, 118(0x76) if CSB=HIGH on WC PCB
Loom_MS5803 ms_air(manager, 118); // 118(0x76) if CSB=HIGH on WC PCB


Loom_LTE lte(manager, NETWORK_APN, NETWORK_USER, NETWORK_PASS);
Loom_MQTT mqtt(manager, lte.getClient(), SECRET_BROKER, SECRET_PORT, DATABASE, BROKER_USER, BROKER_PASS);

// If using Teros 10, Uncoment this line
Loom_Teros10 t10(manager, A2);

// If using SDI12, GS3 or Teros 11 or 12 uncoment this line
//Loom_SDI12 sdi(manager, A2);

// Called when the interrupt is triggered 
void isrTrigger(){
  hypnos.wakeup();
}

void setup() {

  // Wait 20 seconds for the serial console to open
  manager.beginSerial();

  // Enable the hypnos rails
  hypnos.enable();

  // Initialize all in-use modules
  manager.initialize();

  // Register the ISR and attach to the interrupt
  hypnos.registerInterrupt(isrTrigger);
}

void loop() {

  // Measure and package the data
  manager.measure();
  manager.package();
  
  // Print the current JSON packet
  manager.display_data();            

  // Log the data to the SD card              
  hypnos.logToSD();

  // Publish the collected data to MQTT
  mqtt.publish();
//  manager.pause(5000);

  // Set the RTC interrupt alarm to wake the device in 15 min
  hypnos.setInterruptDuration(TimeSpan(0, 0, 15, 0));

  // Reattach to the interrupt after we have set the alarm so we can have repeat triggers
  hypnos.reattachRTCInterrupt();
  
  // Put the device into a deep sleep, operation HALTS here until the interrupt is triggered
  hypnos.sleep();
  
}

Serial print:
[SD Manager] Initializing SD Card...
[SD Manager] Successfully initialized SD Card!
[SD Manager] Data will be logged to 4Gchime17.csv
[Hypnos] DS3231 Real-Time Clock Initialized Successfully!
[Manager] Initializing Modules...
[SHT31] Successfully initialized SHT31!
[TSL2591] Successfully initialized TSL2591!
[MS5803] Successfully Initialized!
[MS5803] Successfully Initialized!
[LTE] Powering up GPRS Modem. This should take about 10 seconds...
[LTE] Powering up complete!
[LTE] Modem Information: Manufacturer: u-blox Model: SARA-R410M-02B Revision: L0.0.00.00.05.08 [Apr 17 2019 19:34:02] SVN: 03 IMEI: 355523760070757
[LTE] Waiting for network...
[LTE] Connected to network!
[LTE] Attempting to connect to LTE Network: hologram
[LTE] Successfully Connected!
[LTE] Connected!
[LTE] APN: hologram
[LTE] Signal State: 99
[LTE] IP Address: 100.71.133.128
[LTE] Attempting to verify internet connection...
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Fri, 30 Sep 2022 23:39:23 GMT
Content-Type: text/plain; charset=UTF-8
Content-Length: 121
Connection: close
X-Powered-By: Express
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: X-Requested-With
Cross-Origin-Resource-Policy: cross-origin
Accept-Ranges: bytes
Cache-Control: public, max-age=86400
Last-Modified: Wed, 27 Sep 2017 09:03:12 GMT
ETag: W/"79-15ec2936080"


|  | |\ | \_/ |  ___ |_____ |  |  |
|  | | \|  |  |_____| _____||  |  |

[LTE] Module successfully initialized!
[Manager] ** Setup Complete **
[Hypnos] Registering RTC interrupt...
[Hypnos] Interrupt successfully attached!

[Manager] Data Json:
{
"type": "data",
"id": {
"name": "4Gchime",
"instance": 10
},
"contents": [
{
"module": "Packet",
"data": {
"Number": 1
}
},
{
"module": "Analog",
"data": {
"Vbat": 4.368310452,
"Vbat_MV": 4347.363281
}
},
{
"module": "SHT31",
"data": {
"Temperature": 23.89999962,
"Humidity": 55.52000046
}
},
{
"module": "TSL2591",
"data": {
"Visible": 530,
"Infrared": 500,
"Full_Spectrum": 1031
}
},
{
"module": "MS5803",
"data": {
"Temperature": 25.43000031,
"Pressure": 1006.280029
}
},
{
"module": "LTE",
"data": {
"RSSI": 23
}
},
{
"module": "Teros 10",
"data": {
"Millivolt_Reading": 845.3480225,
"Dielectric_Permittivity": 1.150050879,
"Volumetric_Water_Content": -0.195306107
}
}
],
"timestamp": {
"time_utc": "2022-09-30 23:39:33",
"time_local": "2022-09-30 16:39:33"
}
}

[SD Manager] Successfully logged data to 4Gchime17.csv
[MQTT] Creating new MQTT client!
[MQTT] Attempting to connect to broker: cas-mosquitto.biossys.oregonstate.edu:1883
[MQTT] Successfully connected to broker!
[MQTT] Attempting to send data...
[MQTT] Data has been successfully sent!
[Hypnos] Current Time: 2022.09.30 16:39:39
[Hypnos] Next Interrupt Alarm Set For: 2022.09.30 16:54:39
[Hypnos] Interrupt successfully reattached!
[LTE] Powering down GPRS Modem. This should take about 5 seconds...
[LTE] Powering down complete!
[Hypnos] Entering Standby Sleep...

Weatherchimes WiFi example, removing/replacing coin cell causes strange behavior

WeatherChimes WiFi example. Testing after programming and Normal behavior is verified. I want to remove the coin cell battery from the hypnos, and replace, so I can set the correct local time.

I reveive printout that power was lost on the RTC, but no prompt to enter the time. Time proceeds in 2001.

These are the printouts I get:

[SD Manager] Initializing SD Card...
[SD Manager] Successfully initialized SD Card!
[SD Manager] Data will be logged to Chime4.csv
[Hypnos] DS3231 Real-Time Clock Initialized Successfully!
[Manager] Initializing Modules...
[SHT31] Failed to initialize SHT31! Check connections and try again...
[TSL2591] Successfully initialized TSL2591!
[SDI12] Initializing SDI-12 Sensors...
[SDI12] Scanning SDI-12 Address Space this make take a little while...
[SDI12] == We found the following active Addresses ==
[SDI12] Address: 0
[WiFi] Initializing WiFi module...
[WiFi] Attempting to connect to SSID: OSU_Access
[WiFi] Connected to network!
[WiFi] Verifying Connection to the Internet...
[WiFi] Ping Failed! Error Code: Ping_TimeOut
[WiFi] Successfully Initalized Wifi!
[WiFi] Device IP Address: 10.248.203.184
[WiFi] Device Subnet Address: 255.254.0.0
[Manager] ** Setup Complete **
[Hypnos] Registering RTC interrupt...
[Hypnos] Interrupt successfully attached!
[Hypnos] Current Time: 2000.01.01 00:01:34
[Hypnos] Next Interrupt Alarm Set For: 2001.08.28 01:28:14

Code here:

/**
 * In lab use case example for the WeatherChimes project
 * 
 * This project uses SDI12, TSL2591 and an SHT31 sensor to log environment data and logs it to both the SD card and also MQTT/MongoDB
 * 
 * MANAGER MUST BE INCLUDED FIRST IN ALL CODE
 */

#include <Loom_Manager.h>

#include <Hardware/Loom_Hypnos/Loom_Hypnos.h>

#include <Sensors/Loom_Analog/Loom_Analog.h>
#include <Sensors/SDI12/Loom_SDI12/Loom_SDI12.h>
#include <Sensors/I2C/Loom_SHT31/Loom_SHT31.h>
#include <Sensors/I2C/Loom_TSL2591/Loom_TSL2591.h>

#include <Internet/Connectivity/Loom_Wifi/Loom_Wifi.h>
#include <Internet/Logging/Loom_MQTT/Loom_MQTT.h>

Manager manager("Chime", 4);

// Analog for reading battery voltage
Loom_Analog analog(manager);

// Create a new Hypnos object
Loom_Hypnos hypnos(manager, HYPNOS_VERSION::V3_2, TIME_ZONE::PST);

// Create the TSL2591 and SHT classes
Loom_SHT31 sht(manager);
Loom_TSL2591 tsl(manager);
Loom_SDI12 sdi(manager, 11);

Loom_WIFI wifi(manager);
Loom_MQTT mqtt(manager, wifi.getClient());

// Called when the interrupt is triggered 
void isrTrigger(){
  hypnos.wakeup();
}

void setup() {

  // Wait 20 seconds for the serial console to open
  manager.beginSerial();

  // Enable the hypnos rails
  hypnos.enable();

  // Load the WiFi login credentials from a file on the SD card
  wifi.loadConfigFromJSON(hypnos.readFile("wifi_creds.json"));
  mqtt.loadConfigFromJSON(hypnos.readFile("mqtt_creds.json"));

  // Initialize all in-use modules
  manager.initialize();

  // Register the ISR and attach to the interrupt
  hypnos.registerInterrupt(isrTrigger);
}

void loop() {

  // Set the RTC interrupt to trigger 10 seconds from when the device woke up
  hypnos.setInterruptDuration(TimeSpan(0, 0, 0, 10));

  // Measure and package the data
  manager.measure();
  manager.package();
  
  // Print the current JSON packet
  manager.display_data();            

  // Log the data to the SD card              
  hypnos.logToSD();

  // Publish the collected data to MQTT
  mqtt.publish();

  // Reattach to the interrupt after we have set the alarm so we can have repeat triggers
  hypnos.reattachRTCInterrupt();
  
  // Put the device into a deep sleep, operation HALTS here until the interrupt is triggered
  hypnos.sleep(false);
}

Max31856 Loom not working, raw example code does

Describe the bug
Max 31856 raw example (oneShot.ino) gives good data on serial monitor.
Loom version prints errors and bad reading.

This is the example code that works:

// Basic example using one-shot measurement.
// The call to readThermocoupleTemperature() is blocking for O(100ms)

#include <Adafruit_MAX31856.h>

// Use software SPI: CS, DI, DO, CLK
//Adafruit_MAX31856 maxthermo = Adafruit_MAX31856(10, 11, 12, 13);
// use hardware SPI, just pass in the CS pin
Adafruit_MAX31856 maxthermo = Adafruit_MAX31856(10);

void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10);
  Serial.println("MAX31856 thermocouple test");

  maxthermo.begin();

  maxthermo.setThermocoupleType(MAX31856_TCTYPE_K);

  Serial.print("Thermocouple type: ");
  switch (maxthermo.getThermocoupleType() ) {
    case MAX31856_TCTYPE_B: Serial.println("B Type"); break;
    case MAX31856_TCTYPE_E: Serial.println("E Type"); break;
    case MAX31856_TCTYPE_J: Serial.println("J Type"); break;
    case MAX31856_TCTYPE_K: Serial.println("K Type"); break;
    case MAX31856_TCTYPE_N: Serial.println("N Type"); break;
    case MAX31856_TCTYPE_R: Serial.println("R Type"); break;
    case MAX31856_TCTYPE_S: Serial.println("S Type"); break;
    case MAX31856_TCTYPE_T: Serial.println("T Type"); break;
    case MAX31856_VMODE_G8: Serial.println("Voltage x8 Gain mode"); break;
    case MAX31856_VMODE_G32: Serial.println("Voltage x8 Gain mode"); break;
    default: Serial.println("Unknown"); break;
  }

}

void loop() {
  Serial.print("Cold Junction Temp: ");
  Serial.println(maxthermo.readCJTemperature());

  Serial.print("Thermocouple Temp: ");
  Serial.println(maxthermo.readThermocoupleTemperature());
  // Check and print any faults
  uint8_t fault = maxthermo.readFault();
  if (fault) {
    if (fault & MAX31856_FAULT_CJRANGE) Serial.println("Cold Junction Range Fault");
    if (fault & MAX31856_FAULT_TCRANGE) Serial.println("Thermocouple Range Fault");
    if (fault & MAX31856_FAULT_CJHIGH)  Serial.println("Cold Junction High Fault");
    if (fault & MAX31856_FAULT_CJLOW)   Serial.println("Cold Junction Low Fault");
    if (fault & MAX31856_FAULT_TCHIGH)  Serial.println("Thermocouple High Fault");
    if (fault & MAX31856_FAULT_TCLOW)   Serial.println("Thermocouple Low Fault");
    if (fault & MAX31856_FAULT_OVUV)    Serial.println("Over/Under Voltage Fault");
    if (fault & MAX31856_FAULT_OPEN)    Serial.println("Thermocouple Open Fault");
  }
  delay(1000);
}

This example in loom does not work:

/**
 * Temperature Readings using teh MAX31865 sensor
 * Pass in a variable number of arguments to the construct to designate the number of samples and which pin you're using
 * 
 * MANAGER MUST BE INCLUDED FIRST IN ALL CODE
 */


#include <Loom_Manager.h>

#include <Sensors/SPI/Loom_MAX318XX/Loom_MAX31856.h>


Manager manager("Device", 1);

// Reads the temperature
Loom_MAX31856 maxDude(manager);

void setup() {

  // Start the serial interface
  manager.beginSerial();

  // Initialize the manager
  manager.initialize();

  // Measure the data from the sensors
  manager.measure();

  // Package the data into JSON
  manager.package();

  // Print the JSON document to the Serial monitor
  manager.display_data();

}

void loop() {
  // put your main code here, to run repeatedly:

}

This prints the following:
[Manager] Initializing Modules...
[Manager] ** Setup Complete **
[MAX31856] Cold Junction Range Fault
[MAX31856] Thermocouple Range Fault
[MAX31856] Cold Junction High Fault
[MAX31856] Cold Junction Low Fault
[MAX31856] Thermocouple High Fault
[MAX31856] Thermocouple Low Fault
[MAX31856] Over/Under Voltage Fault
[MAX31856] Thermocouple Open Fault

[Manager] Data Json:
{
"type": "data",
"id": {
"name": "Device",
"instance": 1
},
"contents": [
{
"module": "Packet",
"data": {
"Number": 1
}
},
{
"module": "MAX31856",
"data": {
"Temperature": null
}
}
]
}

RTC Drift

Describe the bug
RTC Drifting over periods of time.
Note that the source of the issues is RESOLVED at the time of this post. See Additional Context.

Hardware in Use
Hypnos v3.3 (with coin cell)
Feather M0

  • other regular FloDar components

To Reproduce
Steps to reproduce the behavior:

  1. Remove and replace hypnos' coin cell
  2. Upload FloDar lab or field code
  3. Let run for several hours preferably several days.
  4. See error

Expected behavior
The drift gets larger over time. It is unclear whether the drift is linear or not. The time should start correctly. The compile correctly grabs the time at upload. This means that starting times appear correct. Note that when the same unit is given new code and correct compile time, then code is re-uploaded after a significant period of time, the re-upload does not fix the drift that had occurred in the time passed. Thus, during second or third tests, it appears that the start time is incorrect. Assuming start time is correct, and after being run for significant time, the time that has been logged is always behind (lagging) the real time. The amount of the drift varies across several units. However this issue is repeatable on all units.

Code

/**
 * This is an example use case for the FloDar project
 * 
 * NOTE: THIS EXAMPLE DOESN'T WAIT FOR SERIAL AFTER SLEEPING
 * MANAGER MUST BE INCLUDED FIRST IN ALL CODE
 * 
 * MAX31856 is currently unused, so disabled to save compile time
 * Thermocouple unused as well, however is attached to ADS1115
 */

#include <Loom_Manager.h>

#include <Hardware/Loom_Hypnos/Loom_Hypnos.h>
#include <Sensors/I2C/Loom_ADS1115/Loom_ADS1115.h>
#include <Sensors/Loom_Analog/Loom_Analog.h>
// Currently unused
//#include <Sensors/SPI/Loom_MAX318XX/Loom_MAX31856.h>

// Sleep Duration
#define DAY    0
#define HOUR   0
#define MINUTE 15
#define SECOND 0

// Wait to measure (milliseconds)
#define DELAY 10000

// Analog to Flowrate Conversion Formula Constants
#define MAXBITS     16384
#define MAXFLOWRATE 150

Manager manager("Device", 1);

// Create a new Hypnos object setting the version to determine the SD Chip select pin, and starting without the SD card functionality
Loom_Hypnos hypnos(manager, HYPNOS_VERSION::V3_3, TIME_ZONE::PST);
Loom_Analog analog(manager);
Loom_ADS1115 ads(manager);
// Currently unused
//Loom_MAX31856 max56(manager);

// Analog to Flowrate Conversion Formula
float calcFlowRate(){
    return (((float)ads.getAnalog(3) / MAXBITS) * MAXFLOWRATE);
}

// Called when the interrupt is triggered 
void isrTrigger(){
  hypnos.wakeup();
}

void setup() {

  // Start the serial interface
  manager.beginSerial();

  if (DELAY/1000 >= SECOND + 1 && MINUTE == 0 && HOUR == 0 && DAY == 0) {
    Serial.println("You need more time between measurements!");
    return;
  }

  // Enable the hypnos rails
  hypnos.enable();

  // Called after enable
  manager.initialize();

  // Register the ISR and attach to the interrupt
  hypnos.registerInterrupt(isrTrigger);
}

void loop() {
  // Set the RTC interrupt alarm to wake the device in given time
  hypnos.setInterruptDuration(TimeSpan(DAY, HOUR, MINUTE, SECOND));

  // Wait for USFM to boot up before taking data
  delay(DELAY);

  // Measure and package data
  manager.measure();
  manager.package();

  // Add the flow rate to the package
  manager.addData("Flow Meter", "Flow Rate", calcFlowRate());
  
  // Print the current JSON packet
  manager.display_data();            

  // Log the data to the SD card              
  hypnos.logToSD();

  // Reattach to the interrupt after we have set the alarm so we can have repeat triggers
  hypnos.reattachRTCInterrupt();

  // Put the device into a deep sleep, operation HALTS here until the interrupt is triggered
  hypnos.sleep(false);
}

Additional context
THIS ISSUE HAS BEEN RESOLVED AT THE TIME OF BEING POSTED.

The issue is with the delay(DELAY); command. This command relies on the Feather's clock speed to wait for a number of "milliseconds" which is calculated by the feather according to the feather's clock speed. Feather clock speeds vary significantly, and thus large variance in this delay() function can be found between feather and compared against real time.

THE SOLUTION is to use manager.pause(DELAY); instead, as this uses loom and the RTC to pause the code for the correct amount of time and is unaffected by the feather clock speed. This has been tested on several FloDar units and confirmed fixed.

Missing loop content in ADS1115 example

Loop content in Loom ADS1115 example ought to have the following lines:
manager.measure();
manager.package();

manager.display_data();

manager.pause(4000);

Loom V4 Digital values don't change

The values on the Digital pins don't change state from 0.
I am using a button that is normally disconnected. one side going to ground, the other to Digital Pin 10.
I need Loom4 to enable INPUT_PULLUP. I think this is not being done by Loom.

When I manually specify pinMode(10, INPUT_PULLUP);
in the SETUP, the readings function properly. Let's look at how Loom3 handled Digital pin declarations (input, input pullup, output)

Spaces in JSON labels need replaced with underscore

Spaces in names in JSON labeleing of sensor data can create parsing errors where spaces are not allowed in certain applications, Max right now, but likely in other apps too.
Go through all labels and replace spaces with _ underscore please!

LTE 4G shield cannot connect to network

Describe the bug
Attempting to use the 4G LTE board from Will to connect WeatherChimes sensors to internet for MongoDB uploads.
Shield powers up and communicates with M0, but does not connect to network.

BTW: I had to switch the hardware switches on the 4G board to "Hardware SPI" and power from "Shield." Both switches were switched to the other sides (software spi and power from Arduino)
Board would not work in those original switched configurations, but setting to the new positions got the board power and communication.
What was the reason for that?

I notice the example on Loom also has an arduino_secrets.h tab, but I thought we transitioned to an SD card JSON file for this. Am I running out of date code?

One last issue; the program hangs if LET cannot find the internet signal - It should instead carry on and log minimally to SD, and also allow WiFi to be used if declared as needing to be used, as a backup (e.g. if a wifi M0 is used on the 4G board, we should also be able to enable WiFi logging too as a just-in-case backup if we want).

Hardware in Use
Weatherchimes PCB, M0, SaraR4 4G board, TSL2590, MS5803, GS3
Hypnos

To Reproduce
Run below code, taken from WeatherChimes 4G example on Loom.

Expected behavior
Should connect to internet and log sensors to MongoDB

Code

/**
 * In lab use case example for the WeatherChimes project
 * 
 * This project uses SDI12, TSL2591 and an SHT31 sensor to log environment data and logs it to both the SD card and also MQTT/MongoDB
 * 
 * MANAGER MUST BE INCLUDED FIRST IN ALL CODE
 */
#include "arduino_secrets.h"

#include <Loom_Manager.h>

#include <Hardware/Loom_Hypnos/Loom_Hypnos.h>

#include <Sensors/Loom_Analog/Loom_Analog.h>
#include <Sensors/SDI12/Loom_SDI12/Loom_SDI12.h>
#include <Sensors/I2C/Loom_SHT31/Loom_SHT31.h>
#include <Sensors/I2C/Loom_TSL2591/Loom_TSL2591.h>
#include <Sensors/I2C/Loom_MS5803/Loom_MS5803.h>

#include <Internet/Logging/Loom_MQTT/Loom_MQTT.h>
#include <Internet/Connectivity/Loom_LTE/Loom_LTE.h>

Manager manager("Chime", 7);

// Analog for reading battery voltage
Loom_Analog analog(manager);

// Create a new Hypnos object
Loom_Hypnos hypnos(manager, HYPNOS_VERSION::V3_3, TIME_ZONE::PST);

// Create the TSL2591 and SHT classes
Loom_SHT31 sht(manager);
Loom_TSL2591 tsl(manager);
Loom_SDI12 sdi(manager, 10);
Loom_MS5803 ms(manager, 119); // 119(0x77) if CSB=LOW default, 118(0x76) if CSB=HIGH

Loom_LTE lte(manager, NETWORK_APN, NETWORK_USER, NETWORK_PASS);
Loom_MQTT mqtt(manager, lte.getClient(), SECRET_BROKER, SECRET_PORT, DATABASE, BROKER_USER, BROKER_PASS);

// Called when the interrupt is triggered 
void isrTrigger(){
  hypnos.wakeup();
}

void setup() {

  // Wait 20 seconds for the serial console to open
  manager.beginSerial();

  // Enable the hypnos rails
  hypnos.enable();

  // Initialize all in-use modules
  manager.initialize();

  // Register the ISR and attach to the interrupt
  hypnos.registerInterrupt(isrTrigger);
}

void loop() {

  // Measure and package the data
  manager.measure();
  manager.package();
  
  // Print the current JSON packet
  manager.display_data();            

  // Log the data to the SD card              
  hypnos.logToSD();

  // Publish the collected data to MQTT
  mqtt.publish();

  // Set the RTC interrupt alarm to wake the device in 10 seconds
  hypnos.setInterruptDuration(TimeSpan(0, 0, 0, 30));

  // Reattach to the interrupt after we have set the alarm so we can have repeat triggers
  hypnos.reattachRTCInterrupt();
  
  // Put the device into a deep sleep, operation HALTS here until the interrupt is triggered
  hypnos.sleep();
}

** Arduino Secrets Tab **
you know what it looks like.

Output
[SD Manager] Initializing SD Card...
[SD Manager] Successfully initialized SD Card!
[SD Manager] Data will be logged to Chime55.csv
[Hypnos] DS3231 Real-Time Clock Initialized Successfully!
[Manager] Initializing Modules...
[LTE] Powering up GPRS Modem. This should take about 10 seconds...
[LTE] Powering up complete!
[LTE] Modem Information: Manufacturer: u-blox Model: SARA-R410M-02B Revision: L0.0.00.00.05.08 [Apr 17 2019 19:34:02] SVN: 03 IMEI: 355523762522961
[LTE] Waiting for network...
[LTE] No Response from network!
[LTE] Module failed to initialize
Oversampling setting: 512
C0 = 36
C1 = 39571
C2 = 37127
C3 = 25726
C4 = 24863
C5 = 32993
C6 = 28679
C7 = 14613
p_crc: 21
n_crc: 5
[MS5803] Successfully Initialized!
[SDI12] Initializing SDI-12 Sensors...
[SDI12] Scanning SDI-12 Address Space this make take a little while...
[SDI12] == We found the following active Addresses ==
[SDI12] Address: 0
[SHT31] Failed to initialize SHT31! Check connections and try again...
[TSL2591] Successfully initialized TSL2591!
[Manager] ** Setup Complete **
[Hypnos] Registering RTC interrupt...
[LTE] Not initialized!

Additional context
Add any other context about the problem here.

Need MS5803 sensor examples

We need an example of using 1 ms5803, and another example of using 2 of these with the different addresses (118, 119)
Here's some very messy code I was working on using both, please clean up to only the necessary things.

/**
 * In lab test example of using 2 MS5803 sensors each set to different address
 * 
 * This project uses a hypnos, MS5803 with CBS pin on GND and another MS5803 with CBS pin on VCC
 * Calculate Water Height using difference of 2 pressure sensors and formulas from:
 * https://byjus.com/water-pressure-formula/
 * (Pwater-Pair)/0.0981 = water height in millimeters
 * Convert millibar into Pascals: 1Pa = 0.01 millibar
 * https://www.unitconverters.net/pressure/pascal-to-millibar.htm
 * MANAGER MUST BE INCLUDED FIRST IN ALL CODE
 */
#include <Loom_Manager.h>
//#include <Wire.h>
#include <Hardware/Loom_Hypnos/Loom_Hypnos.h>
#include <Sensors/I2C/Loom_MS5803/Loom_MS5803.h>

float height = 0; // in millimeters
float coeficient = 10.1936; // take reciprocal of 0.0981 so we can multiply instead of divide  (100mBar * 1000mm) / (1000kg.over.metercube * 9.81meterspersecondsquare)
float Pw = 1; // Pressure water in millibar
float Pa = 1; // Pressure air in millibar

Manager manager("WC_MS_test", 1);

// Create a new Hypnos object
Loom_Hypnos hypnos(manager, HYPNOS_VERSION::V3_3, TIME_ZONE::PST);

// Sensors to use
// Pressure of Water
Loom_MS5803 ms77(manager, 119); // MS5803 CSB pin pulled GND i2c addr 0x77

// Pressure of Air
Loom_MS5803 ms76(manager, 118); // MS5803 CSB pin pulled VCC i2c addr 0x76

// Might be desirable to pull sleep interval from SD card, not relevant to sketch, disregard
//TimeSpan sleepInterval; // Sleep interval pulled from JSON file on SD Card, see setup

// ISR not used in loop, no sleep in use
// Called when the interrupt is triggered 
void isrTrigger(){
  hypnos.wakeup();
}

void setup() {

  // Wait 20 seconds for the serial console to open
  manager.beginSerial();

  // Enable the hypnos rails
  hypnos.enable();
  manager.initialize();

//  sleepInterval = hypnos.getSleepIntervalFromSD("SD_config.json");
  // Register the ISR and attach to the interrupt
  hypnos.registerInterrupt(isrTrigger);
}

void loop() {

  // Measure and package the data
  manager.measure();
  manager.package();
/*
  // Calculate water height
  Pw = ms77.getPressure();
  Pa = ms76.getPressure();
  height = (Pw-Pa)*coeficient;

  // Add height to the package
  manager.addData("MS5803both", "WaterHeight_mm", height);
*/
  // Print the current JSON packet
  manager.display_data();            

  // Log the data to the SD card              
//  hypnos.logToSD();
  manager.pause(5000);
// If Using Sleep, uncomment:

  // Set the RTC interrupt alarm to wake the device in 10 seconds
  //hypnos.setInterruptDuration(sleepInterval); // if using sd card sleep interval
//  hypnos.setInterruptDuration(TimeSpan(0, 0, 0, 10)); // if not using sd card sleep interval

  // Reattach to the interrupt after we have set the alarm so we can have repeat triggers
//  hypnos.reattachRTCInterrupt();
  
  // Put the device into a deep sleep, operation HALTS here until the interrupt is triggered
//  hypnos.sleep(false);

}

Evaporometer example code not working

Evaporometer code initializes everything successfully but does not write to SD nor output json data to serial. If starts up every 30 seconds but does not write.

Pin interrupt issue waking M0 from sleep and solution

The current implementation of the SparkFun LowPower library only allows pin interrupts of type LOW.
Working with this type, attaching and detaching interrupts can be a hassle and confusing to many just getting started.
Working with Falling, rising, and change would be easier and much more flexible in the variety of trigger types to wake the M0 from sleep.

This was not an issue in Loom 3 and below because of all the abstraction of the Digital module and Interrupts module in old Loom. However, we are asking users now to manage their own pin interrupts and async timers for transparency. BUT it is making it harder to figure out how to wake the M0 beyond the Hypnos baked in interrupt functionality for the RTC which is stable.

Describe the solution you'd like
LowPower library from sparkfun does not have rising, falling, and change features patched. But
https://www.arduino.cc/reference/en/libraries/arduino-low-power/
Arduino Low Power library does. This has been tested on the Feather M0 in OPEnS Lab.
I would like to propose changing sleep functions over to Arduino Low Power library.

Additional context
Dependency for the Library is RTCZero Library.

RTC won't register interrupt when using GSM shield WeatherChimes Integration Hell

Describe the bug
RTC won't register the interrupt when using the GSM shield on the WeatherChimes 4G code on Integration Hell branch
Order of initialization of components looks suspicious on printouts.

Hardware in Use
Hypnos V3_2, WiFi M0, GSM board, Weatherchimes PCB, I left other sensor unplugged.
Note I get a different printout and order when I use the Hypnos V3_3. See comment below

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Code

/**
 * In lab use case example for the WeatherChimes project
 * 
 * This project uses SDI12, TSL2591 and an SHT31 sensor to log environment data and logs it to both the SD card and also MQTT/MongoDB
 * 
 * MANAGER MUST BE INCLUDED FIRST IN ALL CODE
 */
#include "arduino_secrets.h"

#include <Loom_Manager.h>

#include <Hardware/Loom_Hypnos/Loom_Hypnos.h>

#include <Sensors/Loom_Analog/Loom_Analog.h>
#include <Sensors/SDI12/Loom_SDI12/Loom_SDI12.h>
#include <Sensors/I2C/Loom_SHT31/Loom_SHT31.h>
#include <Sensors/I2C/Loom_TSL2591/Loom_TSL2591.h>
#include <Sensors/I2C/Loom_MS5803/Loom_MS5803.h>

#include <Internet/Logging/Loom_MQTT/Loom_MQTT.h>
#include <Internet/Connectivity/Loom_LTE/Loom_LTE.h>

Manager manager("Chime", 7);

// Analog for reading battery voltage
Loom_Analog analog(manager);

// Create a new Hypnos object
Loom_Hypnos hypnos(manager, HYPNOS_VERSION::V3_2, TIME_ZONE::PST);

// Create the TSL2591 and SHT classes
Loom_SHT31 sht(manager);
Loom_TSL2591 tsl(manager);
Loom_SDI12 sdi(manager, A0);
Loom_MS5803 ms_water(manager, 119); // 119(0x77) if CSB=LOW external, 118(0x76) if CSB=HIGH on WC PCB
//Loom_MS5803 ms_air(manager, 118); // 118(0x76) if CSB=HIGH on WC PCB


Loom_LTE lte(manager, NETWORK_APN, NETWORK_USER, NETWORK_PASS);
Loom_MQTT mqtt(manager, lte.getClient(), SECRET_BROKER, SECRET_PORT, DATABASE, BROKER_USER, BROKER_PASS);

// Called when the interrupt is triggered 
void isrTrigger(){
  hypnos.wakeup();
}

void setup() {

  // Wait 20 seconds for the serial console to open
  manager.beginSerial();

  // Enable the hypnos rails
  hypnos.enable();

  // Initialize all in-use modules
  manager.initialize();

  // Register the ISR and attach to the interrupt
  hypnos.registerInterrupt(isrTrigger);
}

void loop() {

  // Measure and package the data
  manager.measure();
  manager.package();
  
  // Print the current JSON packet
  manager.display_data();            

  // Log the data to the SD card              
  hypnos.logToSD();

  // Publish the collected data to MQTT
  mqtt.publish();

  // Set the RTC interrupt alarm to wake the device in 10 seconds
  hypnos.setInterruptDuration(TimeSpan(0, 0, 5, 0));

  // Reattach to the interrupt after we have set the alarm so we can have repeat triggers
  hypnos.reattachRTCInterrupt();
  
  // Put the device into a deep sleep, operation HALTS here until the interrupt is triggered
  hypnos.sleep();
}

Output
[SD Manager] Initializing SD Card...
[SD Manager] Successfully initialized SD Card!
[SD Manager] Data will be logged to Chime20.csv
[Hypnos] DS3231 Real-Time Clock Initialized Successfully!
[Manager] Initializing Modules...
[SHT31] Failed to initialize SHT31! Check connections and try again...
[TSL2591] Failed to initialize TSL2591! Check connections and try again...
[SDI12] Initializing SDI-12 Sensors...
[SDI12] Scanning SDI-12 Address Space this make take a little while...
[SDI12] == No SDI-12 Devices Were Discovered ==
[LTE] Powering up GPRS Modem. This should take about 10 seconds...
[LTE] Powering up complete!
[LTE] Modem Information: Manufacturer: u-blox Model: SARA-R410M-02B Revision: L0.0.00.00.05.08 [Apr 17 2019 19:34:02] SVN: 03 IMEI: 355523762522953
[LTE] Waiting for network...
[LTE] Connected to network!
[LTE] Attempting to connect to LTE Network:
[LTE] Successfully Connected!
[LTE] Connected!
[LTE] APN:
[LTE] Signal State: 21
[LTE] IP Address: 100.71.133.128
[LTE] Attempting to verify internet connection...
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Fri, 16 Sep 2022 19:31:35 GMT
Content-Type: text/plain; charset=UTF-8
Content-Length: 121
Connection: close
X-Powered-By: Express
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: X-Requested-With
Cross-Origin-Resource-Policy: cross-origin
Accept-Ranges: bytes
Cache-Control: public, max-age=86400
Last-Modified: Wed, 27 Sep 2017 09:03:12 GMT
ETag: W/"79-15ec2936080"


|  | |\ | \_/ |  ___ |_____ |  |  |
|  | | \|  |  |_____| _____||  |  |

[LTE] Module successfully initialized!
[Manager] ** Setup Complete **
[Hypnos] Registering RTC interrupt...

Additional context
Add any other context about the problem here.

SDI 12 does not identify sensors when wired to Pin10 and using Hypnos 3_3

Describe the bug
SDI 12 GS3 sensor works on old weatherchimes hardware wired to Pin9 and using Hypnos 3_2
It does not get recognized when wired to pin10 and using Hypnos 3_3

Hardware in Use
Feather M0 wifi, TSL2591, SDI12 GS3, SHT30
Hypnos 3_3

To Reproduce
Upload the WC sensor test code with Weatherchimes 4G board and sensors connected
Observe serial monitor

Expected behavior
SDI12 shoudl recognize GS3 on pin 10

Code

/**
 * WeatherChimes Sensor Test Code
 * i2c SHT30 Temp Humid, SDI12 GS3 Soil Tmp EC VWC, i2c TSL2591 Light Ful Vis
 * Log to SD, report to serial
 * MANAGER MUST BE INCLUDED FIRST IN ALL CODE
 */
#include <Loom_Manager.h>

#include <Hardware/Loom_Hypnos/Loom_Hypnos.h>
#include <Sensors/SDI12/Loom_SDI12/Loom_SDI12.h>
#include <Sensors/I2C/Loom_SHT31/Loom_SHT31.h>
#include <Sensors/I2C/Loom_TSL2591/Loom_TSL2591.h>

Manager manager("Device", 1);

// Create a new Hypnos object setting the version to determine the SD Chip select pin
Loom_Hypnos hypnos(manager, HYPNOS_VERSION::V3_3, TIME_ZONE::PST);
// Create the TSL2591 and SHT classes
Loom_SHT31 sht(manager);
Loom_TSL2591 tsl(manager);
Loom_SDI12 sdi(manager, 10);



void setup() {

  manager.beginSerial();
  
  // Enable the hypnos rails
  hypnos.enable();
  manager.initialize();
}

void loop() {
  manager.measure();
  manager.package();

  manager.display_data();

  manager.pause(5000);
}

Additional context
Add any other context about the problem here.

Relay missing digital control pin to specify

Describe the bug
in the Max_Relay Example code. Running the example with Max does not work.
Device shows "Connected". Serial printouts show receiving the correct state. There is nowhere for the user to specify which pin is the control pin for the Relay. This is done in hardware using the solder jumper, and expected to specify in hardware which solder jumper is used to control the relay from a digital pin.

Hardware in Use
Feather M0 WiFi, Power Relay Featherwing, Computer running Max

To Reproduce
Run the Max_Relay Example code and Max.

Expected behavior
Setting the state in Max should change the physical state of the relay. For now, it is only printing the correct state, but not changing setting the relay state in hardware via the digital pin.

Code

/**
 * This is an example use case for Max controlled Relay
 * 
 * MANAGER MUST BE INCLUDED FIRST IN ALL CODE
 */
#include "arduino_secrets.h"

#include <Loom_Manager.h>

#include <Internet/Connectivity/Loom_Wifi/Loom_Wifi.h>
#include <Internet/Publishing/Loom_Max.h>
#include <Hardware/Actuators/Loom_Relay/Loom_Relay.h>


Manager manager("Device", 21);

Loom_WIFI wifi(manager, SECRET_SSID, SECRET_PASS);
Loom_Max maxMsp(manager, wifi, new Loom_Relay());


void setup() {

  manager.beginSerial();
  manager.initialize();
}

void loop() {
  manager.package();
  manager.display_data();

  // Send and Recieve data from Max
  maxMsp.publish();
  maxMsp.subscribe();
  delay(1000);
}

Additional context
Add any other context about the problem here.

Loom Max breaking change on 4.0.6 but works on 4.0.5

Describe the bug
Loom Max does not work in 4.0.6 but does in 4.0.5

Hardware in Use
M0 WiFi and Wattson board.

To Reproduce
Upload included code in 4.0.5 to see working, then same in 4.0.6 to see bug.

Expected behavior
4.0.6 build and code should work for Loom Max

Code

/**
 * This is an example use case for using the MPU gyroscope in conjunction with max
 * 
 * MANAGER MUST BE INCLUDED FIRST IN ALL CODE
 */
#include "arduino_secrets.h"

#include <Loom_Manager.h>

#include <Internet/Connectivity/Loom_Wifi/Loom_Wifi.h>
#include <Internet/Communication/Loom_Max.h>
#include <Sensors/I2C/Loom_MPU6050/Loom_MPU6050.h>
#include <Sensors/Loom_Analog/Loom_Analog.h>
#include <Sensors/Loom_Digital/Loom_Digital.h>
#include <Hardware/Actuators/Loom_Neopixel/Loom_Neopixel.h>


Manager manager("Wattson", 11);

//Loom_WIFI wifi(manager, CommunicationMode::CLIENT, SECRET_SSID, SECRET_PASS); // Use this line if connection should be in Client mode using router SSID and password from arduino_secrets.h tab
Loom_WIFI wifi(manager, CommunicationMode::AP); // Use this line if WiFi connection should be in Access Point mode

Loom_Max maxMsp(manager, wifi, new Loom_Neopixel()); // register neopixel and wifi to the manager
Loom_MPU6050 mpu(manager);
// Read the battery voltage and A0 and A1
Loom_Analog analog(manager, A0, A1);
// Reads the button on pin 10
Loom_Digital digital(manager, 10, 9);


void setup() {

  manager.beginSerial();
  manager.initialize();
}

void loop() {
  manager.measure();
  manager.package();
  manager.display_data();

  // Send and Recieve data from Max
  maxMsp.publish();
  maxMsp.subscribe();
  manager.pause(40);
}

Config
arduino_secrets.h tab has
#define SECRET_SSID "SSID"
#define SECRET_PASS "Password"

4.0.5 Output

[Manager] Initializing Modules...
[WiFi] Initializing WiFi module...
[WiFi] Starting access point on: Wattson11
[WiFi] Waiting for a device to connect to the access point...
[WiFi] Device connected to AP!
[WiFi] Successfully Initalized Wifi!
[WiFi] Device IP Address: 192.168.1.1
[WiFi] Device Subnet Address: 255.255.255.0
[Max Pub/Sub] Initializing Max Communication....
[Max Pub/Sub] Listening for UDP Packets on 9011
[Max Pub/Sub] Connections Opened!
[Max Pub/Sub] Initializing desired actuators...
[Neopixel0] Succsessfully initialized Neopixel
[Max Pub/Sub] Successfully initialized actuators!
[MPU6050] Calibrating Gyroscope...
[MPU6050]

Calculating gyro offsets
DO NOT MOVE MPU6050...
Done!
X : -8.99
Y : -0.27
Z : -2.48
Program will start after 3 seconds

[MPU6050] Successfully initialized sensor!
[Manager] ** Setup Complete **

[Manager] Data Json:
{
"type": "data",
"id": {
"name": "Wattson",
"instance": 11,
"ip": [
192,
168,
1,
1
]
},
"contents": [
{
"module": "Packet",
"data": {
"Number": 1
}
},
{
"module": "WiFi",
"data": {
"SSID": "Wattson11",
"RSSI": -40
}
},
{
"module": "MPU6050",
"data": {
"ax": 0.077148438,
"ay": -0.027587891,
"az": 0.951660156,
"gx": -0.075242043,
"gy": 0.009842157,
"gz": 0.049153566,
"roll": -0.535746872,
"pitch": -0.024032213,
"yaw": 0.336652786
}
},
{
"module": "Analog",
"data": {
"A0": 29,
"A1": 15,
"Vbat": 4.363476753
}
},
{
"module": "Digital",
"data": {
"9": 0,
"10": 1
}
}
]
}

[Max Pub/Sub] Sending packet to 192.168.1.255:8011
[Max Pub/Sub] Packet successfully sent!
[Max Pub/Sub] No message received!

**4.0.6 output **
[Manager] Initializing Modules...
[MPU6050] Calibrating Gyroscope...
[MPU6050]

Calculating gyro offsets
DO NOT MOVE MPU6050...
Done!
X : -0.67
Y : -59.55
Z : -8.75
Program will start after 3 seconds

[MPU6050] Successfully initialized sensor!
[Max Pub/Sub] Initializing Max Communication....
[Max Pub/Sub] Listening for UDP Packets on 9002
[Max Pub/Sub] Connections Opened!
[Max Pub/Sub] Initializing desired actuators...
[Neopixel0] Succsessfully initialized Neopixel
[Max Pub/Sub] Successfully initialized actuators!
[WiFi] Initializing WiFi module...
[WiFi] Starting access point on: Wattson2
[WiFi] Waiting for a device to connect to the access point...
[WiFi] Device connected to AP!
[WiFi] Successfully Initalized Wifi!
[WiFi] Device IP Address: 192.168.1.1
[WiFi] Device Subnet Address: 255.255.255.0
[Manager] ** Setup Complete **

[Manager] Data Json:
{
"type": "data",
"id": {
"name": "Wattson",
"instance": 2,
"ip": [
192,
168,
1,
1
]
},
"contents": [
{
"module": "Packet",
"data": {
"Number": 1
}
},
{
"module": "Analog",
"data": {
"A0": 2178,
"A1": 31,
"Vbat": 0.041894533
}
},
{
"module": "Digital",
"data": {
"9": 0,
"10": 1
}
},
{
"module": "MPU6050",
"data": {
"ax": -0.052001953,
"ay": -0.001953125,
"az": 1.078125,
"gx": -10.03211975,
"gy": 54.866642,
"gz": 7.798936844,
"roll": -250.9406128,
"pitch": 1372.463013,
"yaw": 199.0600586
}
},
{
"module": "WiFi",
"data": {
"SSID": "Wattson2",
"RSSI": -100
}
}
]
}

[Max Pub/Sub] Sending packet to 0.0.0.255:8002
[Max Pub/Sub] An error occurred when attempting to close the current packet!
[Max Pub/Sub] No message received!

Additional context
Add any other context about the problem here.

Adding mV calculation to Analog module; Teros 10 sensor calculation support

We will need to add into the Arduino code for WeatherChimes how to calculate Dialectic Permittivity and perhaps Volumetric Water Content in addition to the raw analog values, and pack them into the Loom packet. The datasheet to find these formulas is here: http://publications.metergroup.com/Manuals/20788_TEROS10_Manual_Web.pdf

Equation 6 is Dialec Perm and Equation 2 is VWC

Note - we need to calculate millivolts first from the ADC reading. We are doing this with internal functions in the ADS1115 when using that, but we are using the A0 port on the M0 instead, so in Loom, we ought to calculate mV and log it automatically so we can pull this value if needed. You can convert ADC value to millivolts with these easy equations here:

https://learn.sparkfun.com/tutorials/analog-to-digital-conversion/relating-adc-value-to-voltage

Teros10 needs raw mV output and logged

At the moment, mV on the Teros10 is calculated to derive VWC and DP, but we also need mV to be logged with VWC and DP;
All that needs to be done is add a line in the package function for Teros10 to include the mV calculation.

Roll - Pitch for MPU6050 flipped

MPU6050 module outputs accelerometer and gyroscope data in the correct order, but Roll and Pitch are swapped. We just need to make the data being sent under "Roll" to be sent on the "Pitch" label, and vice versa.

Loom Max Servo error

In the Loom Max Servo example,
I can set the value to set the servo position from Max, and I get feedback from the Loom device that the servo value was set by looking at the sensor module in Max, which indicates the new servo position.
But the servo itself does not move.
I do not think we are calling Dispatch to actually tell the servo to go to the target position, or there is an error in that worksflow somewhere.

Prints for relay should reflect the pin number of the relay control pin

Describe the bug
Serial prints of the Max_Relay example code report [Relay0] instead of the pin number of the specified control pin. this would provide useful feedback to the user to ensure they see which relay pin a status printout is referring to.

Hardware in Use
Power relay, Feather WiFi, Max on computer

To Reproduce
Run Max_Relay example with hardware and send commands from Max

Expected behavior
A clear and concise description of what you expected to happen.

Code

/**
 * This is an example use case for Max controlled Relay
 * 
 * MANAGER MUST BE INCLUDED FIRST IN ALL CODE
 */
#include "arduino_secrets.h"

#include <Loom_Manager.h>

#include <Internet/Connectivity/Loom_Wifi/Loom_Wifi.h>
#include <Internet/Communication/Loom_Max.h>
#include <Hardware/Actuators/Loom_Relay/Loom_Relay.h>


Manager manager("Device", 1);

Loom_WIFI wifi(manager, SECRET_SSID, SECRET_PASS);
Loom_Max maxMsp(manager, wifi, CommunicationMode::CLIENT, new Loom_Relay(10));


void setup() {

  manager.beginSerial();
  manager.initialize();
}

void loop() {
  manager.package();
  manager.display_data();

  // Send and Recieve data from Max
  maxMsp.publish();
  maxMsp.subscribe();
  delay(1000);
}

Additional context
Printout from the serial window:
[Max Pub/Sub] Sending packet to 192.168.1.255:8001
[Max Pub/Sub] Packet successfully sent!
[Relay0] Relay pin is set to: HIGH

[Manager] Data Json:
{
"type": "data",
"id": {
"name": "Device",
"instance": 1,
"ip": [
192,
168,
1,
4
]
},
"contents": [
{
"module": "Packet",
"data": {
"Number": 12
}
}
]
}

[Max Pub/Sub] Sending packet to 192.168.1.255:8001
[Max Pub/Sub] Packet successfully sent!
[Relay0] Relay pin is set to: LOW

[Manager] Data Json:
{
"type": "data",
"id": {
"name": "Device",
"instance": 1,
"ip": [
192,
168,
1,
4
]
},
"contents": [
{
"module": "Packet",
"data": {
"Number": 13
}
}
]
}

[Max Pub/Sub] Sending packet to 192.168.1.255:8001
[Max Pub/Sub] Packet successfully sent!
[Relay0] Relay pin is set to: HIGH

GSM cannot connect to internet

Running a striped-down example of WeatherChimes 4G with only Analog to see if it works.
I can register the 4G board with the register example code on Loom.
But, printouts indicate it cannot connect to internet.
Also strangely, the initialization of things appears to be way out of order as same in the full WeatherChimes code:
[SD Manager] Initializing SD Card...
[SD Manager] Successfully initialized SD Card!
[SD Manager] Data will be logged to Chime2.csv
[Hypnos] DS3231 Real-Time Clock Initialized Successfully!
[Manager] Initializing Modules...
[LTE] Powering up GPRS Modem. This should take about 10 seconds...
[LTE] Powering up complete!
[LTE] Modem Information: Manufacturer: u-blox Model: SARA-R410M-02B Revision: L0.0.00.00.05.08 [Apr 17 2019 19:34:02] SVN: 03 IMEI: 355523762522953
[LTE] Waiting for network...
[LTE] Connected to network!
[LTE] Attempting to connect to LTE Network:
[LTE] Connection failed 1/ 10. Retrying...
[LTE] Connected!
[LTE] APN:
[LTE] Signal State: 19
[LTE] IP Address: 100.71.133.128
[LTE] Attempting to verify internet connection...
[LTE] Failed to contact TinyGSM example your internet connection may not be completely established!
[LTE] Module successfully initialized!
[Manager] ** Setup Complete **
[Hypnos] Registering RTC interrupt...

[Manager] Data Json:
{
"type": "data",
"id": {
"name": "Chime",
"instance": 7
},
"contents": [
{
"module": "Packet",
"data": {
"Number": 1
}
},
{
"module": "Analog",
"data": {
"Vbat": 4.350585938,
"Vbat_MV": 4326.416016
}
},
{
"module": "LTE",
"data": {
"RSSI": 99
}
}
],
"timestamp": {
"time_utc": "2022-09-16 21:14:12",
"time_local": "2022-09-16 14:14:12"
}
}

[SD Manager] Successfully logged data to Chime2.csv
[MQTT] Creating new MQTT client!
[MQTT] Attempting to connect to broker: :1883

Remove space in between Teros and 10 for Max Parsing

The Teros 10 sensor label has a space in the name.
For now, this confuses the Max weatherchimes parser. I know dumb.
We don't have spaces between letters and numbers in other labels either though and should be consistent.
Make the label: Teros10

SDI12 reports 0s every other time

SDI12 reports data, but is still reporting 0s for everything every other reading. Is it possible to add a check on the first reading that if all data received is 0 to request another reading? But not to get stuck in a forever loop if 0 keeps getting reported.

Even if it is a hardware instability, adding this robustness in the code will be helpful.

Loom_Hypnos cpp has RTC interrupt pin hard coded in places

In the Loom_Hypnos.cpp, it appears the interrupt pin assignment for functions are hard coded to pin 12.
For example:
void Loom_Hypnos::wakeup(){
detachInterrupt(digitalPinToInterrupt(12)); // Detach the interrupt so it doesn't trigger again
}

And yet, Hypnos RTC functionality seems to work even though Loom_Hypnos.h has
V3_2 = 10,
V3_3 = 11

Any ideas why this is the case?

Be able to set time zone from SD JSON parameter

Is your feature request related to a problem? Please describe.
Loom-programmed devices can end up in different time zones after programming, but the only way to set the timezone is during programming. We can currently set sample period via a file on the SD Card. Is it possible to add an option timezone field in the JSON for people to set it? Timezone should still default to the programmed time zone if the SD card info is not found , not defined, or null.

Loom Max Connectivity, transition from Client to AP mode

For Max Wifi connectivity - When devices are programmed in Client Mode to join a Wifi router - After 10 tries to connect to router have failed, the device should revert to AP Mode and broadcast an SSID based on their name and instance number and connect as if in AP mode. The current code does not make this transition. See serial prints and code below:
[Manager] Initializing Modules...
[WiFi] Initializing WiFi module...
[WiFi] Attempting to connect to SSID: LoomHub4
[WiFi] Attempting to connect to AP...
[WiFi] Attempting to connect to AP...
[WiFi] Attempting to connect to AP...
[WiFi] Attempting to connect to AP...
[WiFi] Attempting to connect to AP...
[WiFi] Attempting to connect to AP...
[WiFi] Attempting to connect to AP...
[WiFi] Attempting to connect to AP...
[WiFi] Attempting to connect to AP...
[WiFi] Attempting to connect to AP...
[WiFi] Failed to connect to the access point after 10 tries! Is the network in range and are your credentials correct?
[WiFi] Verifying Connection to the Internet...
[WiFi] Ping Failed! Error Code: Unknown_Host
[WiFi] Successfully Initalized Wifi!
[WiFi] Device IP Address: 0.0.0.0
[WiFi] Device Subnet Address: 0.0.0.0
[Max Pub/Sub] Initializing Max Communication....
[Max Pub/Sub] Listening for UDP Packets on 9000
[Max Pub/Sub] Connections Opened!
[Max Pub/Sub] Initializing desired actuators...
[Neopixel0] Succsessfully initialized Neopixel
[Max Pub/Sub] Successfully initialized actuators!
[MPU6050] Calibrating Gyroscope...
[MPU6050]

Calculating gyro offsets
DO NOT MOVE MPU6050...
Done!
X : -10.57
Y : -0.87
Z : -2.49
Program will start after 3 seconds

[MPU6050] Successfully initialized sensor!
[Manager] ** Setup Complete **

[Manager] Data Json:
{
"type": "data",
"id": {
"name": "Wattson",
"instance": 0,
"ip": [
0,
0,
0,
0
]
},
"contents": [
{
"module": "Packet",
"data": {
"Number": 1
}
},
{
"module": "WiFi",
"data": {
"SSID": null,
"RSSI": -100
}
},
{
"module": "MPU6050",
"data": {
"ax": 0.130859375,
"ay": 0.337158203,
"az": 1.175292969,
"gx": 1.258118629,
"gy": 5.561841965,
"gz": -1.372692585,
"roll": 8.732762337,
"pitch": 37.22684479,
"yaw": -9.400198936
}
},
{
"module": "Analog",
"data": {
"A0": 53,
"A0_MV": 42.71062088,
"A1": 30,
"A1_MV": 24.17582512,
"Vbat": 4.376367092,
"Vbat_MV": 4374.755859
}
},
{
"module": "Digital",
"data": {
"9": 0,
"10": 1
}
}
]
}

[Max Pub/Sub] Sending packet to 0.0.0.255:8000
[Max Pub/Sub] Packet successfully sent!
[Max Pub/Sub] No message received!

/**
 * This is an example use case for using the MPU gyroscope in conjunction with max
 * 
 * MANAGER MUST BE INCLUDED FIRST IN ALL CODE
 */
#include "arduino_secrets.h"

#include <Loom_Manager.h>

#include <Internet/Connectivity/Loom_Wifi/Loom_Wifi.h>
#include <Internet/Communication/Loom_Max.h>
#include <Sensors/I2C/Loom_MPU6050/Loom_MPU6050.h>
#include <Sensors/Loom_Analog/Loom_Analog.h>
#include <Sensors/Loom_Digital/Loom_Digital.h>
#include <Hardware/Actuators/Loom_Neopixel/Loom_Neopixel.h>


Manager manager("Wattson", 0);

Loom_WIFI wifi(manager, CommunicationMode::CLIENT, SECRET_SSID, SECRET_PASS); // Use this line if connection should be in Client mode using router SSID and password from arduino_secrets.h tab
//Loom_WIFI wifi(manager, CommunicationMode::AP); // Use this line if WiFi connection should be in Access Point mode

Loom_Max maxMsp(manager, wifi, new Loom_Neopixel()); // register neopixel and wifi to the manager
Loom_MPU6050 mpu(manager);
// Read the battery voltage and A0 and A1
Loom_Analog analog(manager, A0, A1);
// Reads the button on pin 10
Loom_Digital digital(manager, 10, 9);


void setup() {

  manager.beginSerial();
  manager.initialize();
}

void loop() {
  manager.measure();
  manager.package();
  manager.display_data();

  // Send and Recieve data from Max
  maxMsp.publish();
  maxMsp.subscribe();
  manager.pause(40);
}

Set target router SSID, Password from Max feature needs fixed

From Max, it is useful to be able to connect to a Loom device via Access Point Mode, and send it information to save new SSID and Password info and switch to client mode. Loom device should from then on try to connect to a router with the SSID and password info until it receives a new message to update the info. The Loom device should always go back to AP mode after 10 failed attempts to connect to a router in a row.

Command sent from Max looks like:
print: MaxSub c Kalani UdellFamilyWireless
print: MaxSub c Kalani UdellFamilyWireless
js: [0] Cmd : MaxSub c Kalani UdellFamilyWireless
js: {"type":"command","dst":{"name":"test","instance":0},"commands":[{"module":"MaxSub","func":99,"params":["Kalani","UdellFamilyWireless"]}]}

But there is no acknowledgement of receipt of this command on the Arduino Serial monitor.

Can this feature be added back?

Stepper Motor Max example does not work

Describe the bug
Stepper Motor Max example will connect to WiFi client mode; successfully sends packets.
Max side prints errors from Convert_Incoming.js
See printouts and screenshots below

Hardware in Use
WiFi M0, Stepper motor shield, WiFi Router, computer running Max

To Reproduce
Run Max example Stepper

Expected behavior
Stepper sent packets should be properly parsed and are not on the Max side. Max parses well with other actuators and sensors, I suspect bad packets coming from stepper.
Messages from Max should control stepper, these are not indicated as received on the

Code

/**
 * This is an example use case for a Max controlled Stepper motor
 * 
 * MANAGER MUST BE INCLUDED FIRST IN ALL CODE
 */
#include "arduino_secrets.h"

#include <Loom_Manager.h>

#include <Internet/Connectivity/Loom_Wifi/Loom_Wifi.h>
#include <Internet/Communication/Loom_Max.h>
#include <Hardware/Actuators/Loom_Stepper/Loom_Stepper.h>


Manager manager("Device", 1);

Loom_WIFI wifi(manager, SECRET_SSID, SECRET_PASS);
Loom_Max maxMsp(manager, wifi, CommunicationMode::CLIENT, new Loom_Stepper(0));


void setup() {

  manager.beginSerial();
  manager.initialize();
}

void loop() {
  manager.package();
  manager.display_data();

  // Send and Recieve data from Max
  maxMsp.publish();
  maxMsp.subscribe();
  delay(1000);
}

Arduino Serial prints
[Manager] Initializing Modules...
[WiFi] Initializing WiFi module...
[WiFi] Attempting to connect to SSID: LoomHub
[WiFi] Connected to network!
[WiFi] Verifying Connection to the Internet...
[WiFi] Ping Failed! Error Code: Unknown_Host
[WiFi] Successfully Initalized Wifi!
[WiFi] Device IP Address: 192.168.1.4
[WiFi] Device Subnet Address: 255.255.255.0
[Max Pub/Sub] Initializing Max Communication....
[Max Pub/Sub] Listening for UDP Packets on 9001
[Max Pub/Sub] Connections Opened!
[Max Pub/Sub] Initializing desired actuators...
[Max Pub/Sub] Successfully initialized actuators!
[Manager] ** Setup Complete **

[Manager] Data Json:
{
"type": "data",
"id": {
"name": "Device",
"instance": 1,
"ip": [
192,
168,
1,
4
]
},
"contents": [
{
"module": "Packet",
"data": {
"Number": 1
}
}
]
}

[Max Pub/Sub] Sending packet to 192.168.1.255:8001
[Max Pub/Sub] Packet successfully sent!
[Max Pub/Sub] No message received!

[Manager] Data Json:
{
"type": "data",
"id": {
"name": "Device",
"instance": 1,
"ip": [
192,
168,
1,
4
]
},
"contents": [
{
"module": "Packet",
"data": {
"Number": 2
}
}
]
}

[Max Pub/Sub] Sending packet to 192.168.1.255:8001
[Max Pub/Sub] Packet successfully sent!
[Max Pub/Sub] No message received!

[Manager] Data Json:
{
"type": "data",
"id": {
"name": "Device",
"instance": 1,
"ip": [
192,
168,
1,
4
]
},
"contents": [
{
"module": "Packet",
"data": {
"Number": 3
}
}
]
}

[Max Pub/Sub] Sending packet to 192.168.1.255:8001
[Max Pub/Sub] Packet successfully sent!
[Max Pub/Sub] No message received!

Max Screenshot
Add any other context about the problem here.
Screen Shot 2022-08-04 at 10 59 42 AM

Stepper Motor Actuator from Loom3 needs worked into V4

Implementation and LoomV4 Max Subscribe example needs made for the Stepper motor
An additional example in the Actuator section just showing how to send a number of steps and speed manually in code would be useful too.
Possible activity for Jace to learn how to integrate Actuators in Loom and Max Subscribe?

Check Loom4 Analog module 12-bit mode!

The M0 SAMD21 has 12-bit analog ADC pins, but Arduino sets these to 10-bit by default, more normally seen.
We need to Explicitly tell the M0 to set the ADC to 12-bit mode. This was done in older version of Loom, but not seen in the V4 code.
// Set Analog Read Resolution
analogReadResolution(read_resolution);
read-resolution should be set to 12 by default

Important: Need 2 MS5803 sensors on different i2c addr to log at same time

Describe the bug
Attempting to use 2 MS5803 sensors.
Needed to calculate water height, using one pressure sensor above water, the other below. Pressure difference translates to water height.
MS5803 data sheet page 8 allows 2 MS5803 sensors to be used on same system by tying CSB pin to VCC or GND in hardware to make different i2c addresses. VCC=0x76 i2c addr ; GND=0x77 addr

I made a sketch testing using 2, hardware is correct. When Loom Logs, it only logs the last MS5803 read, instead of logging both as unique sensors.

Both MS5803 sensors seem to be successfully initialized in the printout.

Hardware in Use
Hypnos, Feather M0 WiFi, 2 MS5803 sensors with CSB pins configured properly.

To Reproduce
Load included code with above hardware.

Expected behavior
2 distinct MS5803 sensors need to be logged seperately.
There also needs to be a way to differentiate clearly WHICH 5803 the data column belongs to; e.g.
MS5803_77 and MS5803_76

Code

/**
 * In lab test example of using 2 MS5803 sensors each set to different address
 * 
 * This project uses a hypnos, MS5803 with CBS pin on GND and another MS5803 with CBS pin on VCC
 * 
 * MANAGER MUST BE INCLUDED FIRST IN ALL CODE
 */
#include <Loom_Manager.h>

#include <Hardware/Loom_Hypnos/Loom_Hypnos.h>
#include <Sensors/I2C/Loom_MS5803/Loom_MS5803.h>

Manager manager("WC_MS_test", 1);

// Create a new Hypnos object
Loom_Hypnos hypnos(manager, HYPNOS_VERSION::V3_2, TIME_ZONE::PST);

// Sensors to use
Loom_MS5803 ms77(manager, 119); // MS5803 CSB pin pulled GND i2c addr 0x77
Loom_MS5803 ms66(manager, 118); // MS5803 CSB pin pulled VCC i2c addr 0x76

// Might be desirable to pull sleep interval from SD card, not relevant to sketch, disregard
TimeSpan sleepInterval; // Sleep interval pulled from JSON file on SD Card, see setup

// ISR not used in loop, no sleep in use
// Called when the interrupt is triggered 
void isrTrigger(){
  hypnos.wakeup();
}

void setup() {

  // Wait 20 seconds for the serial console to open
  manager.beginSerial();

  // Enable the hypnos rails
  hypnos.enable();
  manager.initialize();

  sleepInterval = hypnos.getSleepIntervalFromSD("SD_config.json");
  // Register the ISR and attach to the interrupt
  hypnos.registerInterrupt(isrTrigger);
}

void loop() {

  // Measure and package the data
  manager.measure();
  manager.package();

  // Print the current JSON packet
  manager.display_data();            

  // Log the data to the SD card              
  hypnos.logToSD();
  manager.pause(5000);
// If Using Sleep, uncomment:
/*
  // Set the RTC interrupt alarm to wake the device in 10 seconds
  hypnos.setInterruptDuration(sleepInterval);

  // Reattach to the interrupt after we have set the alarm so we can have repeat triggers
  hypnos.reattachRTCInterrupt();
  
  // Put the device into a deep sleep, operation HALTS here until the interrupt is triggered
  hypnos.sleep(false);
*/

}

Output
[SD Manager] Initializing SD Card...
[SD Manager] Successfully initialized SD Card!
[SD Manager] Data will be logged to WC_MS_test7.csv
[Hypnos] DS3231 Real-Time Clock Initialized Successfully!
[Manager] Initializing Modules...
Oversampling setting: 512
C0 = 36
C1 = 39571
C2 = 37127
C3 = 25726
C4 = 24863
C5 = 32993
C6 = 28679
C7 = 14613
p_crc: 21
n_crc: 5
[MS5803] Successfully Initialized!
Oversampling setting: 512
C0 = 16
C1 = 42299
C2 = 37213
C3 = 26721
C4 = 25242
C5 = 31870
C6 = 27618
C7 = 23242
p_crc: 202
n_crc: 10
[MS5803] Successfully Initialized!
[Manager] ** Setup Complete **
[Hypnos] Sleep interval successfully loaded from SD!
[Hypnos] Registering RTC interrupt...
[Hypnos] Interrupt successfully attached!

[Manager] Data Json:
{
"type": "data",
"id": {
"name": "WC_MS_test",
"instance": 1
},
"contents": [
{
"module": "Packet",
"data": {
"Number": 1
}
},
{
"module": "MS5803",
"data": {
"Temperature": 23.71999931,
"Pressure": 1012.590027
}
}
],
"timestamp": {
"time_utc": "2022-08-26 0:0:23",
"time_local": "2022-08-25 17:0:23"
}
}

[SD Manager] Successfully logged data to WC_MS_test7.csv

[Manager] Data Json:
{
"type": "data",
"id": {
"name": "WC_MS_test",
"instance": 1
},
"contents": [
{
"module": "Packet",
"data": {
"Number": 2
}
},
{
"module": "MS5803",
"data": {
"Temperature": 23.72999954,
"Pressure": 1012.700012
}
}
],
"timestamp": {
"time_utc": "2022-08-26 0:0:28",
"time_local": "2022-08-25 17:0:28"
}
}

[SD Manager] Successfully logged data to WC_MS_test7.csv

[Manager] Data Json:
{
"type": "data",
"id": {
"name": "WC_MS_test",
"instance": 1
},
"contents": [
{
"module": "Packet",
"data": {
"Number": 3
}
},
{
"module": "MS5803",
"data": {
"Temperature": 23.72999954,
"Pressure": 1012.599976
}
}
],
"timestamp": {
"time_utc": "2022-08-26 0:0:33",
"time_local": "2022-08-25 17:0:33"
}
}

[SD Manager] Successfully logged data to WC_MS_test7.csv

Additional context
Add any other context about the problem here.

Teros10 computeDP formula needs fixed to this:

Change formula to this:
float Loom_Teros10::computeDP(float mV){
return ((1.054 * pow(10, -1)) * exp(2.827 * pow(10, -3) * mV));
}

Used to be this:
float Loom_Teros10::computeDP(float mV){
return ((1.054 * pow(10, -1)) - exp((2.827) * pow(10, -3) * mV));
}

Hypnos Adalogger SD CS pin typo

In Hypnos header file, Adalogger CS pin needs to be 4, not 5:
enum HYPNOS_VERSION{
V3_2 = 10,
V3_3 = 11,
ADALOGGER = 4
};

MUX TCA9548A does not initalize

Describe the bug
MUX example for Loom Sensors does not function. TCA9548A does not initalize.

Hardware in Use
Feather M0 and Multiplexer breakout board for TCA9548A

To Reproduce
Connect hardware, Attach an i2c sensor to one of the 8 ports, or don't - the device should report which sensors, if any, are on which MUX channel.

Expected behavior
MUX should initialize in the serial printouts. Report sensors plugged into the MUX board and on which channel.

Code

/**
 * Uses the I2C Multiplexer to dynamically allow hot swapping of I2C sensors
 * 
 * MANAGER MUST BE INCLUDED FIRST IN ALL CODE
 */


#include <Loom_Manager.h>

#include <Hardware/Loom_Multiplexer/Loom_Multiplexer.h>

Manager manager("Device", 1);

// Reads the battery voltage
Loom_Multiplexer mux(manager);

void setup() {

  // Start the serial interface
  manager.beginSerial();

  // Initialize the manager
  manager.initialize();

  // Measure the data from the sensors
  manager.measure();

  // Package the data into JSON
  manager.package();

  // Print the JSON document to the Serial monitor
  manager.display_data();

}

void loop() {
  // put your main code here, to run repeatedly:

}

Config
In the Arduino IDE while editing the config.json, goto 'Edit' -> 'Copy for HTML' and paste the output of that here

Output
[Manager] Initializing Modules...
[Manager] ** Setup Complete **

[Manager] Data Json:
{
"type": "data",
"id": {
"name": "Device",
"instance": 1
},
"contents": [
{
"module": "Packet",
"data": {
"Number": 1
}
}
]
}

Additional context
Add any other context about the problem here.

Rewording hypnos.sleep(false);

In the finction: hypnos.sleep(false);
It appears to read that we are negating or bypassing the functionality. Is it possible to modify the parameters to make
hypnos.sleep();
the commonly used format, and to assign flags to enable or disable features in a way that reads more intuitively?

ADS1115 not giving expected values for analog readings?

Describe the bug
ADS1115 Code does not report ADC values we expect to receive. Seems some bits are truncated, possibly the data type used to store this data is not correct? ADS1115 is a 16-bit ADC, but gives a data range of 15 bits 0 - 2^15. Because the 16th bit is a sign but used for an alternative mode we don't typically use on the ADS1115 chip called differential mode.
This is bad because the ADS1115 is of many projects: SmartRock, LilyPad, to name some.

** It is unclear if this is a Loom issue, a library issue with the 1115, or something in hardware.

Hardware in Use
Feather M0, ADS1115. then use the SmartRock board

What we need to do
A simple ADS1115 breakout on a breadboard with a feather M0.
Set up a linear trim potentiometer on the breadboard, with one side on VCC, the other side GND, and the middle pin going to the Analog input channel on the ADS1115.
Turn the trip pot all the way to one side, the middle, then the other side. Observe Voltage output on the Osciloscope and the ADS1115 data output in the serial monitor.
Make a table of observed values and post.

Prove if values make sense or not with breadboard basic hardware, then we need to test with the SmartRock board.

add ms580302 example to Loom sensors examples

// This example tests the MS5803
// Be sure to read the data sheet, esp with respect to the CSB pin 
// CBS pin low sets i2c address to 0x77 (119)
// CBS pin tied to VCC sets i2c address to 0x76 (118)
// Yes, addresses were double checked.

#include <Loom_Manager.h>

// Add MS5803 Loomified library
#include <Sensors/I2C/Loom_MS5803/Loom_MS5803.h>

// Make instance of manager
Manager manager("MS5803Test", 1);

// Make instance of moolified MS5803 note i2c address relationship with CBB pin in hardware!
Loom_MS5803 ms76(manager, 118); // MS5803 CSB pin tied to VCC i2c addr 0x76

void setup() {
// Wait 20 seconds for the serial console to open
  manager.beginSerial();
  manager.initialize();

  
}

void loop() {
// Measure and package the data
  manager.measure();
  manager.package();
  // Print the current JSON packet
  manager.display_data();  
  manager.pause(2000);  
  
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.