NCP virtualWrite Woes

Hi-
I have an issue, well two issues. First one is I can’t get the main NCP example to compile. Second is I’m unable to pass a float/doube type to the virtual pin.

Hardware setup:
Running NCP firmware on a ESP8266-01 that is connected via Serial1 to the main MCU, a Sparkfun SAMD21 Mini. Two analog inputs on A0 & A1. My reason I’m using this setup is because I need a good analog inputs for my project and the SAMD21 is prime.

Prob 1 - No float/double:
The ESP8266 and SAMD21 are communicating no problem and the project comes online as it should with the “BlynkNCP_LowLevel” example. I’m reading my analog inputs correctly but I’m losing my decimal precision when I pass it to virtualWrite. So on app/dashboard it is showing the rounded number, not the decimal. Yes it is specified as double data stream. The sketch is based off the “BlynkNCP_LowLevel” example. See yellow in pic for decimals

Prob 2 - NCP compile error on compilation:
The Edgent sketch, “Edgent_NCP” just won’t compile. I fix one error and another immediately pops up. I don’t think it likes the OTA parts of the library but IDK. I’m trying to see if this sketch works for the decimal places but can’t get it to compile.

Thanks! Any wisdom is greatly appreciated!

My Main Program:


#define BLYNK_TEMPLATE_ID "blahblahtoken"
#define BLYNK_TEMPLATE_NAME "KS2 Power"
#define BLYNK_FIRMWARE_VERSION "0.1.0"
#define BLYNK_NCP_SERIAL Serial1
#define BLYNK_NCP_BAUD 230400
#define SerialDbg SerialUSB

#include "ArduinoUtils.h"
#include "SAMD_AnalogCorrection.h"
#include "ATSAMD21_ADC.h"

unsigned long timer2 = 0;

void setup()
{
  SerialDbg.begin(9600);
  waitSerialConsole(SerialDbg);

  if (!ncpSetupSerial())
  {
    return;
  }

  // const char *ncpFwVer = "unknown";
  // if (rpc_blynk_getNcpVersion(&ncpFwVer))
  // {
  //   SerialDbg.print(F("NCP firmware: "));
  //   SerialDbg.println(ncpFwVer);
  // }

  rpc_hw_initLED(13, false);
  rpc_hw_setLedBrightness(50);
  rpc_blynk_setConfigTimeout(30 * 60);
  rpc_blynk_setFirmwareInfo(BLYNK_FIRMWARE_TYPE,
                            BLYNK_FIRMWARE_VERSION,
                            BLYNK_FIRMWARE_BUILD_TIME,
                            BLYNK_RPC_LIB_VERSION);

  if (!rpc_blynk_initialize(BLYNK_TEMPLATE_ID, BLYNK_TEMPLATE_NAME))
  {
    SerialDbg.println(F("rpc_blynk_initialize failed"));
  }

  analogReadResolution(12);
  analogReadCorrection(78, 2088);
  // analogGain(ADC_GAIN_2);
  analogReference2(ADC_REF_INT1V);
}

void loop()
{
  rpc_run();

  if (millis() - timer2 > 1000)
  {
    readAnalog();
    timer2 = millis();
  }
}



void rpc_client_processEvent_impl(uint8_t event)
{
  switch ((RpcEvent)event)
  {
  case RPC_EVENT_NCP_REBOOTING:
    SerialDbg.println(F("NCP is rebooting. TODO: reinitialize NCP"));
    break;
  case RPC_EVENT_BLYNK_PROVISIONED:
    SerialDbg.println(F("NCP finished provisioning"));
    break;
  case RPC_EVENT_BLYNK_TIME_SYNC:
    SerialDbg.println(F("NCP requests time sync from external time source"));
    break;
  case RPC_EVENT_BLYNK_TIME_CHANGED:
    break;
    SerialDbg.println(F("NCP local time changed"));
    break;
  /*
   * User button events (see rpc_hw_initUserButton)
   */
  case RPC_EVENT_HW_USER_CLICK:
    SerialDbg.println(F("NCP: user button click"));
    break;
  case RPC_EVENT_HW_USER_DBLCLICK:
    SerialDbg.println(F("NCP: user button double click"));
    break;
  case RPC_EVENT_HW_USER_LONGPRESS:
    SerialDbg.println(F("NCP: user button long press start"));
    break;
  case RPC_EVENT_HW_USER_LONGRELEASE:
    SerialDbg.println(F("NCP: user button long press stop"));
    break;
  case RPC_EVENT_HW_USER_RESET_START:
    SerialDbg.println(F("NCP: Button is pressed for 10 seconds => release to clear configuration"));
    break;
  case RPC_EVENT_HW_USER_RESET_CANCEL:
    SerialDbg.println(F("NCP: Button is pressed for 15 seconds => cancel config reset operation"));
    break;
  case RPC_EVENT_HW_USER_RESET_DONE:
    SerialDbg.println(F("NCP: Button was released => configuration is reset"));
    break;
  default:
    break;
  }
}

void readAnalog()
{
  unsigned long timer1 = millis();

  int reading0 = 0, maxReading0 = 0;
  int reading1 = 0, maxReading1 = 0;

  while (millis() - timer1 < 2000)
  {
    reading0 = analogRead(A0);
    if (reading0 > maxReading0)
    {
      maxReading0 = reading0;
    }

    reading1 = analogRead(A1);
    if (reading1 > maxReading1)
    {
      maxReading1 = reading1;
    }
  }

  virtualWrite(0, maxReading0);
  virtualWrite(1, maxReading1);

  double voltage0 = maxReading0 * 0.00080566;
  double voltage1 = maxReading1 * 0.00080566;

  virtualWrite(2, voltage0);
  virtualWrite(3, voltage1);

  double amps0 = 10 * voltage0;
  double amps1 = 10 * voltage1;

  virtualWrite(4, amps0);
  virtualWrite(5, amps1);
}

second program file:



#include <Arduino.h>
#include <BlynkRpcClient.h>
#include <BlynkRpcUartFraming.h>

#if !defined(BLYNK_FIRMWARE_TYPE) && defined(BLYNK_TEMPLATE_ID)
#define BLYNK_FIRMWARE_TYPE BLYNK_TEMPLATE_ID
#endif

#if !defined(BLYNK_TEMPLATE_ID) || !defined(BLYNK_TEMPLATE_NAME)
#error "Please specify your BLYNK_TEMPLATE_ID and BLYNK_TEMPLATE_NAME"
#endif

#define BLYNK_FIRMWARE_BUILD_TIME __DATE__ " " __TIME__


#if defined(BLYNK_NCP_SERIAL)
#define SerialNCP BLYNK_NCP_SERIAL
#elif defined(ARDUINO_NANO_RP2040_CONNECT)
#define SerialNCP SerialNina
#elif defined(LINUX)
#include <compat/LibSerialPort.h>
#if !defined(BLYNK_NCP_PORT)
#define BLYNK_NCP_PORT "/dev/ttyUSB0"
#endif
SerialPort SerialUSB(BLYNK_NCP_PORT);
#define SerialNCP SerialUSB
#else
#error "Your board needs extra configuration to work with Blynk.NCP: please define BLYNK_NCP_SERIAL and perform NCP hardware initialization if needed"
#endif

int rpc_uart_available()
{
  // Return the amount of data in the UART input buffer
  return SerialNCP.available();
}
int rpc_uart_read()
{
  // Get a byte from the UART input buffer
  return SerialNCP.read();
}
size_t rpc_uart_write(uint8_t data)
{
  // Put a byte to the UART output buffer
  return SerialNCP.write(data);
}
void rpc_uart_flush()
{
  // Wait for UART to output all the data
  SerialNCP.flush();
}
uint32_t rpc_system_millis()
{
  // Return uptime in milliseconds
  // This is used to implement the RPC timeout
  return millis();
}

#define BLYNK_PARAM_KV(k, v) k "\0" v "\0"

volatile const char firmwareTag[] PROGMEM = "blnkinf\0" BLYNK_PARAM_KV("mcu", BLYNK_FIRMWARE_VERSION)
    BLYNK_PARAM_KV("fw-type", BLYNK_FIRMWARE_TYPE)
        BLYNK_PARAM_KV("build", BLYNK_FIRMWARE_BUILD_TIME)
            BLYNK_PARAM_KV("blynk", BLYNK_RPC_LIB_VERSION) "\0";


bool ncpSetupSerial(uint32_t timeout = 10000)
{
  RpcUartFraming_init();

  const long baudTarget = BLYNK_NCP_BAUD;
  const long baudRates[3] = {38400, 115200, baudTarget};
  unsigned baudIdx = 0;

  const uint32_t tbeg = millis();
  while (millis() - tbeg < timeout)
  {
    long baud = baudRates[baudIdx++ % 3];
    SerialNCP.begin(baud);
    if (RPC_STATUS_OK == rpc_ncp_ping())
    {
      if (baud != baudTarget)
      {
        // Upgrade baud rate
        if (rpc_hw_setUartBaudRate(baudTarget))
        {
          SerialNCP.flush();
          SerialNCP.begin(baudTarget);
          baud = baudTarget;
          delay(20);
          if (RPC_STATUS_OK != rpc_ncp_ping())
          {
            SerialDbg.println(F("Changing NCP baud failed"));
            return false;
          }
        }
      }
      SerialDbg.print(F("Blynk.NCP ready, baud: "));
      SerialDbg.println(baud);
      return true;
    }
  }
  SerialDbg.println(F("NCP not responding"));
  return false;
}

const char *ncpGetStateString(uint8_t state)
{
  switch (state)
  {
  case BLYNK_STATE_IDLE:
    return "Idle";
  case BLYNK_STATE_CONFIG:
    return "Configuration";
  case BLYNK_STATE_CONNECTING_NET:
    return "Connecting Network";
  case BLYNK_STATE_CONNECTING_CLOUD:
    return "Connecting Cloud";
  case BLYNK_STATE_CONNECTED:
    return "Connected";

  case BLYNK_STATE_NOT_INITIALIZED:
    return "Not Initialized";
  case BLYNK_STATE_OTA_UPGRADE:
    return "NCP Upgrade";
  case BLYNK_STATE_ERROR:
    return "Error";

  default:
    return "Unknown";
  }
}

void virtualWrite(int virtualPin, const char *value)
{
  buffer_t val = {(uint8_t *)value, strlen(value)};
  rpc_blynk_virtualWrite(virtualPin, val);
}


void virtualWrite(int virtualPin, double value)
{
  char buff[16];
  itoa(value, buff, 10);
  virtualWrite(virtualPin, buff);
}


template <typename T>
void waitSerialConsole(T &ser)
{
  const uint32_t tstart = millis();
  while (!ser && (millis() - tstart < 2900))
  {
    delay(1);
  }
  delay(100);
}

FYI the Edgent_NCP example sketch compiles successfully for all other boards but the Sparkfun boards. Strange. They throw a variety of errors.

@vshymanskyy