Recording data from two adxl345 sensors

Source Audio's icon

Max 8 one does not post anything if serial object disconnects.

You can add periodic message to max, which would stop if no connection.

Same for your 2 Senders, but use larger interval.

I did not remove this from your original sender code :

if (now - lastHeartbeat >= HEARTBEAT_INTERVAL) {heartbeatPacket.id = 99; heartbeatPacket.x = 0; heartbeatPacket.y = 0; heartbeatPacket.z = 0;

esp_now_send(receiverMAC, (const uint8_t *)&heartbeatPacket, sizeof(SensorPacket));

lastHeartbeat = now;}

you had 500m s interval.

change it to 5 seconds set ID for each sensor like 11 and 12

something like

if (now - lastHeartbeat >= HEARTBEAT_INTERVAL)

{esp_now_send(receiverMAC, (const uint8_t []){11}, 1); lastHeartbeat = now;}

for other sensor use 12

do you want me to post code for all 3 senders and receiver V3 ?

for serial auto-connect to your ESP32 I need ALL asked infos on both mac and win.

F_Dos's icon

do you want me to post code for all 3 senders and receiver V3 ?


This would be highly appreciated

pease delete more posts , like this last one, which is not going to work....


will do so

for serial auto-connect to your ESP32 I need ALL asked infos on both mac and win.

Will do so once at home

F_Dos's icon
Source Audio's icon

receiver CodeV2 had a mistake in setup() by accident I reversed send and receive init.

in case you want to keep using it change this in setup()

esp_now_register_send_cb((esp_now_send_cb_t)onDataRecv);

to this :

esp_now_register_recv_cb(onDataRecv);

.........

here is new code with 5000ms notifications from 2 sensors and ESP host to Max

baud is set to 460800 as in your last posted receiver code

CodeV3.zip
zip 7.52 KB

In max you get S1 S2 and OK every 5000 ms and if it does not get received --- something is wrong

deay time is 100ms longer then pulse, and will not bang when receiving at 5000ms interval

................

what do you want to use for autp record start ? is hour and minute enough ?

F_Dos's icon

what do you want to use for autp record start ? is hour and minute enough ?

Yes hour and minute is enough

regarding the active window time - could you point me to the message you said you show this?

Thanks for the above code I will check it asap!

Source Audio's icon

that shows measured pauses, but also alerts if no input has been received for set time.

Still I am not sure how you want to exactly deal with that

.........

For scheduled recording, one would run date when patch starts using metro 1000

and start recording for set length. in that case making folder and naming files would need to change.

unless you want to schedule several recording starts.

like 10:30 length 2 hours 24.20 length 1 hour 2:30, and 18:00 length 3:20

......

by the way , I can post js code that takes list input of certain length and writes line by line into a file on HD using coll format.

so if you input 1 22 33 44 it writes 1, 22 33 44;

( but you wll need to read files anyway into coll to play or analyse)

if you plan to make any math analysis and want to use excel for that,

one could modify js to write .tsb files (tab delimited cells)

........

F_Dos's icon

if you plan to make any math analysis and want to use excel for that,


Yes that might be the case

by the way , I can post js code that takes list input of certain length and writes line by line into a file on HD using coll format.

Yes sounds great!

Still I am not sure how you want to exactly deal with that


Now I can check for when there's no activity over a certain amount of time. I wanted to look for the opposite — to know when I had a certain amount of activity over x amount of time. For example, if I have 8 hours of recording, I want to easily see at what times in that recording I had actual movement for over x seconds or minutes.


Is this system to write log of active or discconected of Sensor make sense?

edited patch:

Max Patch
Copy patch and select New From Clipboard in Max.

Source Audio's icon

I would use text instead, and write into a file ESP_date_time.txt.

Max Patch
Copy patch and select New From Clipboard in Max.

but maybe you want to try excel one for this ?

F_Dos's icon

Thanks for this patch look great. I will automate it as the other system for recording sensors so it will be in sync.

but maybe you want to try excel one for this ?

why you offered excl? any reason?

Source Audio's icon

because you mentioned you might want to use it for analyses.

it does not have to be excel, I can use tab or space delimiter, and write .tsb

or .txt files

F_Dos's icon

In that case excl it might be better only if it is not complicates things.

Source Audio's icon

main difference is it writes direct to HD, not into max

you just pass a path to EXISTING folder and give it a name.

F_Dos's icon

OK!

regarding the system of showing activity windows of time. is that possible to add to the current system?

Source Audio's icon

I will post js ESP monitor, just say if you want tabs or space delimiter.

F_Dos's icon

space delimiter

Source Audio's icon

ok, folder path MUST EXIST for this to work. name extension .txt is auto added in js

ESPmonitor.zip
zip 3.43 KB


Source Audio's icon

things will become a bit complex when you add auto record, monitoring etc.

if you are not sure, I would make 2 projects, one to manually do all, and one for scheduled recording.

in first place because of creating folder/file structure.

here is one example how to use scheduled record,

it has main functions, but it would need connection to the rest.

record start and length is set in hours minutes, timing is scaled to 1 second.

2 secondes before recording starts, folder and file should be created.

in fact it needs no folder as only 1 recording takes place.

Or you maynbe schedule several recordings using a text file with start - length pairs ?

F_Dos's icon

Or you maynbe schedule several recordings using a text file with start - length pairs ?

If there's a way to mark or view timestamps where movement happened, and jump to them easily during playback, then I don't mind having long recording files — the length itself isn't the issue, navigating within it is. So I don't particularly need scheduled recording, although it's a nice feature to have!

Source Audio's icon

back to this question:

"For example, if I have 8 hours of recording, I want to easily see at what times in that recording I had actual movement for over x seconds or minutes"

Now you mark periods that were inactive if pause is longer then set time.

means in between that marks there are active periods.

in case your pause length remains as threshold, you start recording and first input triggers start time of first active period.

now you want to mark end of that active period when next inactive period happens ?

or to keep adding markers for "still active" if no pause for 20 seconds that you mentioned?

I don't really understand what do you want to write in the log .

F_Dos's icon

Thanks for breaking that down — to clarify: I'm looking for option A. For each active period, I just want a single start/end pair logged: the timestamp when the active period began (right after an inactive period ends), and the timestamp when it ended (right when the next inactive period begins).

I don't need repeated "still active" markers throughout the period — just the two boundary timestamps per active window, similar to how the inactive windows are currently logged as pairs.

So for an 8-hour recording, I'd end up with a list of active windows, each one just two numbers (start, end), and I could then filter for the ones longer than X seconds/minutes.

Source Audio's icon

pause END is START of activity

you write 2 values now, 1 last activity end - 2 new activity start.

in between is a pause.

next line start is next pause start or how long activity was...

So you have all that infos in the coll, only very first activity period is missing,

one could insert it when first value gets in.

F_Dos's icon

Or you maynbe schedule several recordings using a text file with start - length pairs ?

Now I understand what you said here. In that case Yes I would like to scheduale several recordings like something like this: (no need seconds)

F_Dos's icon

next line start is next pause start or how long activity was...

So you have all that infos in the coll, only very first activity period is missing,

That's a really elegant insight — thank you! I understand the logic (previous pause end = next activity start), but I'm not confident I can wire it correctly in the patch myself.

Would you be able to show me how to structure this so the resulting activity windows are also visible in jit.cellblock, similar to how the pause windows are currently displayed there? I'd like to be able to see both the pause list and the derived activity list side by side.

Source Audio's icon

As first one needs one line for rec start and LENGTH.

if you start recording at 23:30 for 3 hours, end would be in next day

23:30 2:30

I would recommend only 2 values

12:22 2:00 rec will end at 14:22

but if you prefer absolute time, ok, it is up to you in which case recording time will not be linked to elapsed recording counter but to date output.

........

for "activity" period logs :

one could revert to not write pauses but active periods, but is that hh:mm:ss format

in 8 hour coll effective to make math ?

you use this :

24:00:44 24:08:19 12:00:44 12:08:19 pause start - end in recording time and absolute day time

now you dump possible 2880000 lines into what ?

F_Dos's icon

Thanks for both explanations!

On scheduling: I'll go with relative time (hour:minute + length), not absolute date-based time. My use case is a recurring daily pattern (e.g. record a few hours each morning and evening), not a one-time date-specific event, so hour:minute fits better and keeps it simpler.

On the activity-period logging and jit.cellblock: that's a fair point about 2,880,000 lines in the worst case — I don't think dumping that many lines into jit.cellblock makes sense for an 8-hour file. Given that, maybe it's better to keep the activity-window derivation logic conceptually as you described (previous pause end = next activity start), but only apply it when I actually need to inspect a specific recording — computing it on demand rather than continuously logging every possible line. Or would you recommend a different approach entirely for handling that volume?

F_Dos's icon

here is the printing of the serial you asked earlier: (MAC laptop)

serial: port a: debug-console

serial: port b: Bluetooth-Incoming-Port

serial: port c: SOUNDPEATSCapsule3Pro

serial: port d: usbmodem1101

serial: port e: usbmodem21101


I wanted to explain something and ask for your advice: when I start a recording with all sensors working fine, and then stop the recording, the sensor-status logger (S1/S2/OK) ends up empty — nothing gets logged.

I have two questions related to this:

1. How can I save/log the current sensor status at the moment recording starts, even if no new S1/S2/OK message happens to arrive right at that exact moment?

2. Alternatively, is there a way to prevent recording from starting at all unless I've already received an OK confirmation from all the sensors? This to prevent that recording start before even open the serial

the above is not really necceseraly therfore can be ignored

F_Dos's icon

I changed the logger name to fit the other files:

input 2 is from record button

input 3 is from [s folderpath]

input 4 is from [s counter]

F_Dos's icon

I run the recording through the night from 21:30 until 07:20 and thanks to the system reporting status I noticed the sensors disconnected few times. and the last one was from 02:00 until I stopped the recording:

Any idea what can it be?

( the first disconnected at 21:52 I made my self because I move the sensor to a difference place and I think I did the same at 22:28 and maybe also 23:00 but I'm not 100% sure)

21:52:32 S1 disconnected

21:52:44 S1 ok

22:28:54 S1 ok

22:28:54 S1 disconnected

23:00:39 S1 disconnected

23:01:09 S1 ok

23:01:48 S2 disconnected

23:01:55 S2 ok

23:04:17 Receiver ok

23:04:17 Receiver disconnected

02:21:29 S1 disconnected

02:21:30 S2 disconnected

02:21:32 Receiver disconnected

edit: the long dissconnected from 02:21 until finished recording is probably cause because my mac went to sleep:

Source Audio's icon

that log is strange, order and timing of log makes no sense

21:52:32 S1 disconnected

21:52:44 S1 ok

22:28:54 S1 ok

22:28:54 S1 disconnected

23:00:39 S1 disconnected

23:01:09 S1 ok

in theory, because of your change inserted, you can not have

multiple ok messages without disconnected and opposite,

and no way to get ok and disconnected at same time ?

it is maybe because how you pack the messages .

I can not control every corner of code you write.

do you have Overdrive on and Audio Interrupt off as it should be ?

also remove all unneeded visual garbage from the patch.

at the end could js play a role ?

you could try to log to text file in parallel and compare.

.......

next thing to check is sender /receiver code, was there a lot of sensor messages

at disconnection time ?

.........

when you load recorded file into coll, you have to analyse pauses and or active periods.

and there you have many lines in 8 hours, if windy, max 2880000.

.......

F_Dos's icon

I will test again with your original unmodified code and see if it works smoothly. The main discconectd I am almost 100% sure happens because my MAC went to sleep

F_Dos's icon

I'm back to your original logger file:

Do you think I should use this same logger (with small changes to make the file readable by coll — adding semicolons, etc.) to also record the data from the 3 sensors? Is it the safest method for that too?

Also, I wanted to circle back to something I asked before — about showing active-time windows instead of inactive/pause windows. Did you have a chance to look into that, or is there anything more you need from me to help build it?

Source Audio's icon

you should turn audio interrupt OFF

F_Dos's icon

you should turn audio interrupt OFF

Did so now.

small updated regarding your new codes:

I made those small changes:

In the Receiver:

  • onDataRecv used esp_now_data_t, I reverted it to the standard v3 signature (const esp_now_recv_info_t *info, const uint8_t *data, int len)

  • The struct copy (packet = sharedPacket) is a direct assignment from a volatile struct, which throws a C++ compile error ("ambiguous overload for operator=") — I went back to copying field-by-field

  • analogRead(A2) was reverted back to A2, but my moisture sensor is wired to A10 — I changed it back

In all 3 Senders:

  • onSent used the old core-2.x signature (const uint8_t *mac_addr, esp_now_send_status_t status), which doesn't match Lib v3 — I restored the correct v3 signature with the explicit cast

I kept the improvements that did work well — the calibrate() guard against the 4-second freeze, and the explicit peerInfo.ifidx = WIFI_IF_STA.

--

Separately from your changes, I also added something of my own: an LED on the Receiver that only pulses when two things happen together — the 5-second Alive/OK heartbeat fires, AND something arrives back from Max over serial in that same window:

if (millis() - Alive >= 5000) {
  Alive = millis();
  Serial.println("OK");

  if (Serial.available() > 0) {
    while (Serial.available() > 0) { Serial.read(); }
    digitalWrite(LED_PIN, LOW);
    ledOn = true;
    blinkOnTime = now;
  }
}

Right now, I have Max sending something back every 5 seconds too, so this effectively confirms the full round-trip (Receiver → Max → Receiver) is alive, not just that the Receiver itself is running.

Everything's uploaded and running now with those fixes and this addition in place.

Source Audio's icon

sorry for the libs confusion, I worked years with most optimal v 1.06, and somewhat with 2.0.17

but v3 is not in my brain.

did you keep that new loop in receiver ?

if (newPacketReceived) {noInterrupts();

I deketed my codev4.

about showing active periods, you should have understood that thy are allready marked with pauses, where pause ends activity starts, whre activity ends,pause starts, when longer then set time,

one only needs to group that 2 number differently.

If you can't manage it, post and I will try but my tume is really short this days

F_Dos's icon

To answer your question directly: no, I didn't keep that specific change. Checking the code, newPacketReceived = false is still placed before noInterrupts(), same as in the original V3. When I fixed the volatile struct assignment (packet = sharedPacket → field-by-field copy), I kept the reset where it originally was, rather than moving it inside the critical section like your V4 attempt did.

Here's the full Receiver code I'm actually running right now, so you can see exactly what's in place:

// ==========================================
// RECEIVER V4 (corrected)
// ==========================================
// THIS IS FOR ESP32 Lib v3 ONLY - 3 axes as LIST, PREFIX to Serial A1 / A2

#include <WiFi.h>
#include <esp_now.h>

unsigned long Alive = 0;
volatile bool signal11Received = false;
volatile bool signal12Received = false;

#define LED_PIN LED_BUILTIN
unsigned long blinkOnTime = 0;
bool ledOn = false;
const unsigned long BLINK_DURATION = 500;

typedef struct {
  uint8_t id;
  float x;
  float y;
  float z;
} SensorPacket;

volatile SensorPacket sharedPacket;
volatile bool newPacketReceived = false;
SensorPacket packet;

float currentM1 = 0.45;
float prevM1 = -1.0;
unsigned long lastMRead = 0;
const float HUMIDITY_THRESHOLD = 0.005;

void onDataRecv(const esp_now_recv_info_t *info, const uint8_t *data, int len) {
  if (len == 1) {
    if (*data == 11) {
      signal11Received = true;
    } else if (*data == 12) {
      signal12Received = true;
    }
  } else if (len == sizeof(SensorPacket)) {
    memcpy((void*)&sharedPacket, data, sizeof(SensorPacket));
    newPacketReceived = true;
  }
}

void checkHumidity() {
  unsigned long now = millis();
  if (now - lastMRead >= 2000) {
    lastMRead = now;
    currentM1 = analogRead(A10) / 4095.0;
    if (abs(currentM1 - prevM1) > HUMIDITY_THRESHOLD) {
      prevM1 = currentM1;
      Serial.print("M1 ");
      Serial.println(currentM1, 3);
    }
  }
}

void setup() {
  Serial.begin(460800);
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);
  WiFi.mode(WIFI_STA);
  if (esp_now_init() != ESP_OK) { while (1); }
  esp_now_register_recv_cb(onDataRecv);
}

void loop() {
  unsigned long now = millis();

  if (ledOn && (now - blinkOnTime >= BLINK_DURATION)) {
    digitalWrite(LED_PIN, HIGH);
    ledOn = false;
  }

  if (signal11Received) {
    signal11Received = false;
    Serial.println("S1");
  }
  if (signal12Received) {
    signal12Received = false;
    Serial.println("S2");
  }

  if (newPacketReceived) {
    newPacketReceived = false;
    noInterrupts();
    packet.id = sharedPacket.id;
    packet.x = sharedPacket.x;
    packet.y = sharedPacket.y;
    packet.z = sharedPacket.z;
    interrupts();

    if (packet.id == 1) {
      Serial.print("A1 ");
      Serial.print(packet.x, 3);
      Serial.print(" ");
      Serial.print(packet.y, 3);
      Serial.print(" ");
      Serial.println(packet.z, 3);
    } else if (packet.id == 2) {
      Serial.print("A2 ");
      Serial.print(packet.x, 3);
      Serial.print(" ");
      Serial.print(packet.y, 3);
      Serial.print(" ");
      Serial.println(packet.z, 3);
    }
  }

  if (millis() - Alive >= 5000) {
    Alive = millis();
    Serial.println("OK");

    if (Serial.available() > 0) {
      while (Serial.available() > 0) { Serial.read(); }
      digitalWrite(LED_PIN, LOW);
      ledOn = true;
      blinkOnTime = now;
    }
  }

  checkHumidity();
}

And understood on the active-periods logic — no rush at all, I know your time is tight right now. If you get a moment at some point to show how you'd wire it, I'd really appreciate it — but I'll try building it myself in the meantime (previous pause-end = next activity-start, grouped in pairs) and will only post again if I get stuck.

Source Audio's icon

ok, i thought that interrupts could have caused that erratic serial traffic with disconnects.

when I come back later I wil send also js code to write coll format

F_Dos's icon

Good thought about interrupts — Looking forward to the js code for the coll format when you have a moment, no rush.

Just to make sure the active-periods request is fully clear: I don't just want to see the active windows themselves — I'd like to be able to filter them by a variable duration threshold, exactly like the inactive/pause system already does with $i3. So I could set it to show only active periods longer than 20 seconds, or 10 seconds, or 3 minutes, etc. — the same flexible threshold approach, just applied to active periods instead of pauses.

I'll try building it myself in the meantime — no rush on your end at all.

Source Audio's icon

this active periods give me a trouble.

you must first define exactly what for you active period is.

then one should see how to gain that information out of indexes stream.

in case of inactivity it was simple, compare current to previous index,

and if abs difference is greater then set time - then it is a pause.

can you describe your activity parameters in such simple formula ?

.......

here is js code to write coll formated text file using list as input.

Only problem with this is that js does not care if indexes repeat,

which coll does and rewrites them,

but in your case with ms progress as input it is not possible to have duplicates anyway.

same as for monitor you must provide existing folder path to create the file.

write-coll.zip
zip 1.88 KB


F_Dos's icon

That's actually clearer, thanks — and I think it means I need two separate thresholds, not one:

1. A small "gap tolerance" — a pause shorter than ~1 second shouldn't break the activity window at all (the sensor is still "active" through it).

2. A separate "minimum duration to display" — after the activity windows are built, filter them by 20s / 10s / 3min etc.

Does that approach better defined?

F_Dos's icon

I try the new js coll to write the sensor data. I have different data from both files:

The left hand side is from SensorA using the coll method and the right hand side is SensorA using the new js code.

I modify as follow:

Edit:

Just to add — the fact that js keeps more data than coll doesn't bother me. I don't think those extra same-millisecond duplicates would have any real musical impact anyway.

What would you recommend going forward — should I keep recording with both methods in parallel (coll and js), or is there a reason to prefer one over the other now that we've seen this difference? Curious what you'd suggest.

Source Audio's icon

Your only way to mark active and unactive periods is to measure pauses, as it is now.

then you could pass lengths between pauses to another comparison.

like what I showed on that screenshot.

Source Audio's icon

the fact that you get more entries per 1 ms I explained - js does not strip duplicates.

but it is strange that you get them in first place. can you try to print captured values ?

makes me wonder if you get duplicates too and then why

F_Dos's icon

OK, thanks for clarifying this. I have to leave home for a day or so, but I'll bang my head around this when I'm back.

Source Audio's icon

I am leaving very soon for a month and won't be able to reply so often

F_Dos's icon

can you try to print captured values ?

You mean to print to the max console the values entering coll and the js ?

F_Dos's icon

console:

Left side is coll txt file, right hand side is js file

Source Audio's icon

in that case you get real duplicates which coll removes.

print and js show exactly the same list.

As I have no time or hardware to test and can not think of anything else then to

remove not essential functions from the code and concentrate on sensor output in max.

adding this useless monitoring functions without being 100 % sure that they don't mess with the flow can be the cause of the problem.

ESP senders will not be able to run from a battery, power consumption is too much for longer period. means remove all power saving functions, remove disconnect detection, blinking,

in short anything that is not essential.

here is competely stripped code for you to test.

everything except sensors send/receive has been removed,

no power saving, CPU at max, serial BAUD back to 115200.

MinimalCode.zip
zip 2.39 KB

if you confirm it works better, then you might try to add your blinking or

disconnect detection, but I am out of that now.

in case you want to keep code as is, and are happy with stripping multiple received

lines of values within 1 ms, coll would do that anyway.

if you prefer to use js, here is code that strips 5 consecutive duplicates.

writeCollDUP.zip
zip 2.01 KB


F_Dos's icon

Thanks so much for all your help throughout this — the sender/receiver codes, the disconnect detection, the js loggers, and all the patient debugging along the way.

Quick update: I tried the minimal stripped-down code you sent. The duplicate-line pattern (js keeping more lines than coll) still showed up even there, so that confirms it's unrelated to the LED/S1/S2/OK monitoring — those weren't the cause. I'm going back to the fuller version with all the indicators, since they're cleared now.

Really appreciate the time you've put into this, especially given how busy things are for you right now. I'll keep testing and report back if anything comes up.