[Announce] node-red-node-Arduino (Firmata) remastered `v1.3.4-20250331`

... after 1+ month (200+ hours of time investment), I proudly present:

The first stable version of Arduino / Firmata module.

Currently it can be downloaded from: here v1.3.3. I'm planning to create a pull request too.

The 1.1 version currently available for download at npm + Github is:

  • not working in many ways,

so I had to rewrite it (almost) completely. (ca. 70 lines left untouched from 770.) The whole process of it is: here...

What changed:

  1. "max pin" problem solved. Now works again with Raspberry Pi - Pico (+ESP32) boards too!

  2. analogue pin checking! (NR crashed before)

  3. more help added to html = setup panels

    • number inputs for pin instead of text,
    • min-max,
    • added more tips & warning,
    • etc...

  1. msg.payload = "reset" >> resets board (more later...)

  2. added many else and constants to speed up execution

  3. renamed variables to be unique. Like: node -> brdNode, nodeIn, nodeOut

  4. added error handling for unhandled errors

  5. changed var to let everywhere

  6. added emit -> to immediate auto-update all in/out nodes
    if master-board state changed !

  7. created clear status definitions. + according visual colour + text status for each

  8. added "sampling interval" (more later ... )

  9. added: log2consol checkbox (setup)

  10. Deploy works !

  11. Partial deploy works also!! :1st_place_medal:
    Even changing 1-1 pin during run without stopping or restart.

  12. msg.payload null warning for Out-node input

  13. added new Out-node types: [RESET, INTERVAL]

  14. Event / emit exceed limit problems of v1.1 solved!

  15. Added: Name config for better naming / label showing

  16. can handle "no board" / "no com set" / "no pin set"

  17. endless "board-search" animation probably solved. (need testing!)

  18. Auto-timed connect retry (100ms - 10sec increasing)

  • so if board gets only later plugged in (after start) >> it works too!
  1. auto-pin-conflict search and show system
  2. version is shown at in+out config panel

+ all kinds of bug fixes ...

About Sampling-interval:

A value of millisecond between 10-65500 can be set ! :+1:

  • Both at startup on the Arduino setup panel,
  • and at runtime via msg.payload = 500 if node-out Type is set for this.

This will reduce or increase the speed, how (analogue) data will flow (if changed).
This is a global value. So individual pins can not be set differently at Firmata firmware.
Default value is now changed from 19ms to: 200ms, because even my high speed laptop could not handle the amount of debugs showing even for 1 pin.

  • 200ms => max 5 message will be sent pro second, if value changes
    (for each analogue pin you subscribed for).

About board-reset:

This function has 2 purpose:

  1. it will stop sending analogue values + will set all output pins to default LOW
  2. helps after restart, because the board can be re-attached to NR.

Note: it happens very fast. So if there is only a "LED blink", you will hardly notice anything, because "output" will work again after a few milliseconds.
Analogue read (and maybe digital in too!) will stop completely until flow restart.

Two ways to do it:

  1. Set Arduino-out node to: reset + send a: msg.payoload = true or 1
  2. Send msg.payload = reset to any "Out" node.

Try it yourself, and leave a comment!

4 Likes
  1. Fixed some sentences at HTML + Readme.md + Help
    (could not figure out, how to embed active URL links into help)
  2. Deleted half of the tips visible up here, as @dceejay requested at his PMs
  3. Log to console default is: OFF (unchecked)
  4. changed version number to: 1.3.3-20250330 (from ..0329)
  5. added help to "Arduino out" node too !
  6. uploaded and requested a Pull at github.

Very bad news:

Just tested:

  • if sampling interval is set to a high value (eg. 2000ms)
  • short pressing digital input will not work!

I wrote to all the help files explanations sentences which suggests: it only affects the analogue ports.

I will open an issue at Configurable-Firmata firmware page, maybe there is a workaround?

Auto-port-search finally fixed!

  1. had to rewrite both (html+JS) functions to async !
  2. added try-catch for error handling
  3. response naming changed to path ! (had to debug for hours...)
  4. added logs to both browser's console & node-red-log (console)
Available Ports: [
  {
    path: 'COM3',
    manufacturer: 'Microsoft',
    serialNumber: '6&35CA52AB&0&0000',
    pnpId: 'USB\\VID_2E8A&PID_00C0&MI_00\\6&35CA52AB&0&0000',
    locationId: '0000.0014.0000.001.000.000.000.000.000',
    friendlyName: 'Soros USB-eszköz (COM3)',
    vendorId: '2E8A',
    productId: '00C0'
  }
]

News:

1. Pull Request created. Waiting for accept of: v1.3.4-20250331.


About earlier:

2. Asked the programmer of Firmata

to enhance the code to be able to accept different setup for different type of pins.

1 Like

Good news:

A code part of Configurable Firmata has been found, prevented reporting of digital pins at higher sampling rate.
Read here...

The only "side effect" is, that fluctuating pins will be reported more times,
but I think that's ok, because usually if someone is not using proper pullup-resistors, it's not a software problem.

After this pull request is accepted, everyone should upgrade his Firmata firmware.


I2C and SPI is also affected, because until now sampling rate was not effecting them.
From now on, it will!

Note:

if using unshielded or long cables, (especially in electric noisy or 110V/240V environment,) it is strongly recommended to use optocoupler. There are complete 4 channel boards under $2 price, and can handle 12V/24V to work stable even at 100/1000 meters of cable.

Changes at: v1.4.1-20250405

  1. In-nodes do not report / send new message on start!

  2. Fixed: Reported "pin conflict" at "String", "sampling rate", etc. types too.

  3. Fixed: Reported "wrong pin" at "String-in" type. (strings do not use Pins)
    _Strings nodes did not accept Pin values, like: 99

  4. String-in node can start before board-report. (no need to wait)
    This way it will report even "...starting" message coming from Firmata board.

  5. Circumvent Firmata-io is reporting "opening port" messages as "Error".
    (while it is not one.)

Noticed behaviour at disconnect:

While unplugging / disconnecting the board, sometimes it can happen, that:

  • Close event

gets called by Node-red Firmata-io, instead of:

  • (transport-) Disconnect event

In these cases it will completely close all sub-nodes, so

In-nodes will stop receiving in-values !

What will still work after reconnecting:

  • Outputs, like turning a Pin High/Low
  • String-in

PS: I have no Wifi capable boards to test, but behaviour will probably the same.
Because Node-RED does not properly propagating the current state of NR service, like:

RED.starting
RED.stopping
RED.started
RED.restarting
RED.flowRestart
RED.deploying

it is nearly impossible to distinguish, why close is happening.

If these values of NR would be available, the nodes could start a repeating:

  • reconnecting + event-re-subscibing function.

About Temperature read at RPi-Pico - SOLVED!

The problem was on CustomFirmata's Firmware side:

  1. The board definition is wrong. There are 31 pins, including 5 analogue. (Not 30 / 4!)
    So, for Pico1 board, you must change the file ...Arduino\libraries
    770. lines to this:

    #define TOTAL_ANALOG_PINS     5
    #define TOTAL_PINS              31
    

    Will add a push req. to Github code soon.

  2. Had to change the resolution to 12 bit. (See code below)

  3. Also IMHO it is essential, to use an up-to-date board library, called: Earle Phil's Arduino-Pico instead of the 4 year old "embedOS".

So, it is necessary adding following lines to the setup() part, before exporting and flashing to RPi-Pico board:

void setup()
{
...
  analogReadResolution(12);
  // send TEMP °C + RawTempValue, formatted as JSON.
#include <stdio.h>
  float c = analogReadTemp();
  char buf[50], buf2[25];
  snprintf(buf , 25, "{\"celsius\": %f, ", c);

#include <hardware/structs/adc.h>
  hw_set_bits(&adc_hw->cs, ADC_CS_TS_EN_BITS);
  delay(1); // Allow things to settle.  Without this, readings can be erratic
  int _rt = analogRead(TOTAL_PINS - 1);
  snprintf(buf2, 25, "\"rawTemp\": %d }", _rt);
  strcat  (buf , buf2);

  Firmata.sendString(F( buf ));	

//  float celsius = 27.0f - ((v * vref / 4096.0f) - 0.706f) / 0.001721f;  // const float vref = 3.3f; 
}

Result during bootup is coming through Adruino-in STRING node:

{"celsius": 23.3933, "rawTemp": 881 }

The main difference was this: analogReadResolution(12);

Without that line, only values like: 219, 220 came always. (Probably because the default resolution is 10bit.)

So now I can read the same values (779-882) with Node-RED too ! :slight_smile:
Anyway the interesting thing is, that even at max resolution (12 bit) the temp values having too big jumps if I apply the math:
Ca. 0.47 °C jumps between 2 values.

860 => 34.628632 
861 => 34.160488 
862 => 33.692379 
863 => 33.224236 
864 => 32.756092 
865 => 32.287949 
866 => 31.819803 
867 => 31.351692 
868 => 30.883549 
869 => 30.415405 
870 => 29.947262 
871 => 29.479116 
872 => 29.011007 
873 => 28.542864 
874 => 28.074718 
875 => 27.606575 
876 => 27.138432 
877 => 26.670322 
878 => 26.202177 
879 => 25.734034 
880 => 25.265888 
881 => 24.797745 
882 => 24.329636 
883 => 23.861492 
884 => 23.393347 
885 => 22.925203 
886 => 22.457060 
887 => 21.988949 
888 => 21.520805 
889 => 21.052662 
890 => 20.584518 
891 => 20.116373 
892 => 19.648264 
893 => 19.180119 
894 => 18.711975 
895 => 18.243832 
896 => 17.775688 
897 => 17.307579 
898 => 16.839434 
899 => 16.371290 
900 => 15.903146 
901 => 15.435001 
902 => 14.966892 
903 => 14.498748 
904 => 14.030603 
905 => 13.562460 
906 => 13.094316 
907 => 12.626206 
908 => 12.158062 
909 => 11.689918 
910 => 11.221774 
911 => 10.753630 
...