Two issues

I used an arduino mkr nb 1500 and worked on platform.io.

Currently I found 2 problems

Firstly, in version 1.3.0 of the blynk library, when I write a double type variable to blynk.virtualwrite, I get an error code during compilation.

The second is that LTE communication is disconnected after about 2 hours.
I used serial.println to find where it stops and it seems to be blynk.run().

void setup()
{ serial.println
  GPIO_init();
  digitalWrite(17, HIGH);

  Serial.begin(9600);
  delay(1000);

  Wire.begin(); // Start I2C communication
  Wire.setClock(3400000UL);

  setupMPU(); // Set up MPU6050
  getMeasurement();

  Blynk.begin(BLYNK_AUTH_TOKEN, nbAccess, gprs, client, pin, "sgp1.blynk.cloud");
  Blynk.run();

  timer.setInterval(60000L, Timer1);
  timer.setInterval(500L, Timer2);
}

void loop()
{ timer.getMeasurement(); }
  getMeasurement();

  if (Blynk.connected())
    Blynk.run();
  else
  }
    Serial.println("Lost connection");
    MODEM.hardReset();
    NVIC_SystemReset();
  }
  Serial.println(F("blynk.run"));

  timer.run();
}

Your full sketch would be more useful than a snippet, and an example of the first issue and compiler error message would also help.

Pete.

@PeteKnight
I’ll give you a full sketch first.
The most important issue is getting stuck in the infinite loop of the blynk.run function.

#include <Arduino.h>

#include <Wire.h>  // I2C 통신과 관련된 라이브러리

#include <MKRNB.h> // MKR NB 보드와 관련된 라이브러리

// Blynk 장치 ID

#define DEVICE_ID 2

// Blynk 설정

#define BLYNK_TEMPLATE_ID "TMPL6lM3nJxMN"

#define BLYNK_TEMPLATE_NAME "Expansion Joint"

const char *BLYNK_AUTH_TOKENS[] = {

    "",

    "DlcXosJtli9mCLRVaUpZmC86vM_9Z4Qk",

    "F0X8EnEl6ZDZ9jGttffSPj9kOGFYkGVU"};

#define BLYNK_AUTH_TOKEN (BLYNK_AUTH_TOKENS[DEVICE_ID])

#include <BlynkSimpleMKRNB.h> // MKR NB 보드용 Blynk 라이브러리

// MKR NB 초기화

NBClient client;

GPRS gprs;

NB nbAccess;

BlynkTimer timer;

char pin[] = "0000";

/*  GPIO

포트 핀 구성

아두이노 포트 핀 기능: pinMode(), digitalRead() 및 digitalWrite()는 기본적으로 어쨌든 이 작업을 수행합니다.

digitalRead() 및 digitalWrite()에 비해 직접 레지스터 조작을 사용하면 약간의 성능 이점만 있습니다.

포트 핀 입력

특정 포트 핀을 입력으로 설정하려면:

PORT->Group[PORTA].PINCFG[19].bit.INEN = 1;  // Enable PA19 input

PORT->Group[PORTA].PINCFG[19].bit.PULLEN = 0;

PORT->Group[PORTA].DIRCLR.reg = PORT_PA19;

풀업 저항으로 입력을 활성화하려면:

PORT->Group[PORTA].PINCFG[19].bit.INEN = 1;  // Enable PA19 input with a pull-up resistor

PORT->Group[PORTA].PINCFG[19].bit.PULLEN = 1;

PORT->Group[PORTA].DIRCLR.reg = PORT_PA19;

PORT->Group[PORTA].OUTSET.reg = PORT_PA19;

풀다운 저항으로 입력을 활성화하려면:

PORT->Group[PORTA].PINCFG[19].bit.INEN = 1;  // Enable PA19 input with a pull-down resistor

PORT->Group[PORTA].PINCFG[19].bit.PULLEN = 1;

PORT->Group[PORTA].DIRCLR.reg = PORT_PA19;

PORT->Group[PORTA].OUTCLR.reg = PORT_PA19;

입력을 읽으려면:

if (PORT->Group[PORTA].IN.reg & PORT_PA19)  // Read the input pin on PA19

포트 핀 출력

특정 포트 핀을 출력으로 설정하려면:

PORT->Group[PORTA].DIRSET.reg = PORT_PA19;  // Set PA19 to an output

PORT->Group[PORTA].PINCFG[19].bit.INEN = 1;  // Support output read back

출력을 높게 설정하려면:

PORT->Group[PORTA].OUTSET.reg = PORT_PA19;  // Set PA19 output HIGH

출력을 낮게 설정하려면:

PORT->Group[PORTA].OUTCLR.reg = PORT_PA19;  // Set PA19 output LOW

Arduino-포트 핀 매핑

예를 들어 디지털 핀 D12의 경우 Arduino "g_APinDescription" 구조를 사용하여 Arduino 핀 번호에서 포트 핀으로 매핑하는 것도 가능합니다.

PORT->Group[g_APinDescription[12].ulPort].PINCFG[g_APinDescription[12].ulPin].bit.INEN = 1;

*/

void GPIO_init()

{

  pinMode(17, OUTPUT);

  analogReadResolution(12);

  // analogReference(AR_DEFAULT) = Set the analogue input threshold to 3.3V

  ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_DIV2_Val;

  ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val;

  // pinMode(A2, OUTPUT);

  PORT->Group[PORTB].DIRSET.reg = PORT_PB03;

  PORT->Group[PORTB].PINCFG[3].bit.INEN = 1;

  // pinMode(D0, INPUT);

  PORT->Group[PORTA].PINCFG[22].bit.INEN = 1;

  PORT->Group[PORTA].PINCFG[22].bit.PULLEN = 0;

  PORT->Group[PORTA].DIRCLR.reg = PORT_PA22;

  // pinMode(D1, OUTPUT);

  PORT->Group[PORTA].DIRSET.reg = PORT_PA23;

  PORT->Group[PORTA].PINCFG[23].bit.INEN = 1;

  // pinMode(D2, INPUT);

  PORT->Group[PORTA].PINCFG[10].bit.INEN = 1;

  PORT->Group[PORTA].PINCFG[10].bit.PULLEN = 0;

  PORT->Group[PORTA].DIRCLR.reg = PORT_PA10;

  // pinMode(D3, OUTPUT);

  PORT->Group[PORTA].DIRSET.reg = PORT_PA11;

  PORT->Group[PORTA].PINCFG[11].bit.INEN = 1;

  // pinMode(D4, INPUT);

  PORT->Group[PORTB].PINCFG[10].bit.INEN = 1;

  PORT->Group[PORTB].PINCFG[10].bit.PULLEN = 0;

  PORT->Group[PORTB].DIRCLR.reg = PORT_PB10;

  // pinMode(D5, OUTPUT);

  PORT->Group[PORTB].DIRSET.reg = PORT_PB11;

  PORT->Group[PORTB].PINCFG[11].bit.INEN = 1;

  // pinMode(D6, INPUT);

  PORT->Group[PORTA].PINCFG[20].bit.INEN = 1;

  PORT->Group[PORTA].PINCFG[20].bit.PULLEN = 0;

  PORT->Group[PORTA].DIRCLR.reg = PORT_PA20;

  // pinMode(D7, OUTPUT);

  PORT->Group[PORTA].DIRSET.reg = PORT_PA21;

  PORT->Group[PORTA].PINCFG[21].bit.INEN = 1;

}

// MPU6050 변수

float Acc_scaleFactor, Gyro_scaleFactor;

const int8_t MPU_ADDR = 0x69;

// mpuData 인덱스 열거형

enum SensorIndex

{

  AcX,

  AcY,

  AcZ,

  Tmp,

  GyX,

  GyY,

  GyZ

};

// MPU6050 레지스터를 설정하는 함수

inline void configureMPURegister(int8_t registerAddr, int8_t value)

{

  Wire.beginTransmission(MPU_ADDR);

  Wire.write(registerAddr);

  Wire.write(value);

  Wire.endTransmission(true);

}

void setupMPU()

{

  // MPU6050 전체(4개) 활성화

  PORT->Group[PORTA].OUTSET.reg = PORT_PA23;

  PORT->Group[PORTA].OUTSET.reg = PORT_PA11;

  PORT->Group[PORTB].OUTSET.reg = PORT_PB11;

  PORT->Group[PORTA].OUTSET.reg = PORT_PA21;

  // MPU6050 초기화 및 리셋

  configureMPURegister(0x6B, 0);    // MPU-6050 활성화

  configureMPURegister(0x6B, 0x03); // 클럭 소스 설정

  /*  가속도계 설정

    AFS_SEL=0, Full Scale Range = +/- 2 [g]

    AFS_SEL=1, Full Scale Range = +/- 4 [g]

    AFS_SEL=2, Full Scale Range = +/- 8 [g]

    AFS_SEL=3, Full Scale Range = +/- 10 [g]

  */

  switch (0)

  {

  case 0:

    configureMPURegister(0x1C, 0x00);

    Acc_scaleFactor = 16384;

    break;

  case 1:

    configureMPURegister(0x1C, 0x08);

    Acc_scaleFactor = 8192;

    break;

  case 2:

    configureMPURegister(0x1C, 0x10);

    Acc_scaleFactor = 4096;

    break;

  default:

    configureMPURegister(0x1C, 0x18);

    Acc_scaleFactor = 3276.8;

    break;

  }

  // 스케일 팩터를 역수로 취함

  Acc_scaleFactor = 1.0 / Acc_scaleFactor;

  /*  자이로스코프 설정

    FS_SEL=0, Full Scale Range = +/- 250 [degree/sec]

    FS_SEL=1, Full Scale Range = +/- 500 [degree/sec]

    FS_SEL=2, Full Scale Range = +/- 1000 [degree/sec]

    FS_SEL=3, Full Scale Range = +/- 2000 [degree/sec]

  */

  switch (0)

  {

  case 0:

    configureMPURegister(0x1B, 0x00);

    Gyro_scaleFactor = 1.0 / 131.0;

    break;

  case 1:

    configureMPURegister(0x1B, 0x08);

    Gyro_scaleFactor = 65.5;

    break;

  case 2:

    configureMPURegister(0x1B, 0x10);

    Gyro_scaleFactor = 32.8;

    break;

  default:

    configureMPURegister(0x1B, 0x18);

    Gyro_scaleFactor = 16.4;

    break;

  }

  // 스케일 팩터를 역수로 취함

  Gyro_scaleFactor = 1.0 / Gyro_scaleFactor;

  /*  DLPF 설정

    Accel BW 260Hz, Delay    0ms / Gyro BW 256Hz, Delay 0.98ms, Fs 8KHz

    Accel BW 184Hz, Delay    2ms / Gyro BW 188Hz, Delay  1.9ms, Fs 1KHz

    Accel BW  94Hz, Delay    3ms / Gyro BW  98Hz, Delay  2.8ms, Fs 1KHz

    Accel BW  44Hz, Delay  4.9ms / Gyro BW  42Hz, Delay  4.8ms, Fs 1KHz

    Accel BW  21Hz, Delay  8.5ms / Gyro BW  20Hz, Delay  8.3ms, Fs 1KHz

    Accel BW  10Hz, Delay 13.8ms / Gyro BW  10Hz, Delay 13.4ms, Fs 1KHz

    Accel BW   5Hz, Delay   19ms / Gyro BW   5Hz, Delay 18.6ms, Fs 1KHz

  */

  configureMPURegister(0x1A, 6);

  // MPU6050 전체(4개) 비활성화

  PORT->Group[PORTA].OUTCLR.reg = PORT_PA23;

  PORT->Group[PORTA].OUTCLR.reg = PORT_PA11;

  PORT->Group[PORTB].OUTCLR.reg = PORT_PB11;

  PORT->Group[PORTA].OUTCLR.reg = PORT_PA21;

}

// 배열 크기 수정요함 (타입, 크기)

int16_t mpuData[4][7];      // [0,1,2,3][AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ] 순으로 저장

int32_t mpuData_prev[4][3]; // [num][data]

const uint8_t MPU_portGroup[4] = {0, 0, 1, 0};

const uint32_t MPU_writePin[4] = {1ul << 23, 1ul << 11, 1ul << 11, 1ul << 21};

const uint32_t MPU_readPin[4] = {1ul << 22, 1ul << 10, 1ul << 10, 1ul << 20};

// MPU6050에서 데이터 읽기

inline void readMPU(uint8_t MPU_num)

{

  // Data Backup

  mpuData_prev[MPU_num][AcX] = mpuData[MPU_num][AcX];

  mpuData_prev[MPU_num][AcY] = mpuData[MPU_num][AcY];

  mpuData_prev[MPU_num][AcZ] = mpuData[MPU_num][AcZ];

  // 해당 핀이 활성화되어 있으면, 무시

  if (PORT->Group[MPU_portGroup[MPU_num]].IN.reg & MPU_readPin[MPU_num])

    return;

  // 해당 핀이 비활성화되어 있으면, MPU 활성화

  else

    PORT->Group[MPU_portGroup[MPU_num]].OUTSET.reg = MPU_writePin[MPU_num];

  // 데이터 읽기

  Wire.beginTransmission(MPU_ADDR);

  Wire.write(0x3B);

  Wire.endTransmission(false);

  // 가속도 데이터만 호출

  Wire.requestFrom(MPU_ADDR, 6, true); // 2byte * 3

  mpuData[MPU_num][AcX] = (Wire.read() << 8 | Wire.read());

  mpuData[MPU_num][AcY] = (Wire.read() << 8 | Wire.read());

  mpuData[MPU_num][AcZ] = (Wire.read() << 8 | Wire.read());

  // MPU 비활성화

  PORT->Group[MPU_portGroup[MPU_num]].OUTCLR.reg = MPU_writePin[MPU_num];

}

double accData[4] = {0.0, 0.0, 0.0, 0.0};

uint32_t soundData = 0;

inline void getMeasurement()

{

  // 소음 측정

  uint32_t soundValue = analogRead(A0);

  if (soundData < soundValue)

    soundData = soundValue;

  // 진동 측정

  uint32_t axisValue;

  double axisValue_double;

  for (int i = 0; i < 4; i++)

  {

    readMPU(i);

    axisValue = abs(mpuData[i][AcX] - mpuData_prev[i][AcX]);

    axisValue += abs(mpuData[i][AcY] - mpuData_prev[i][AcY]);

    axisValue += abs(mpuData[i][AcZ] - mpuData_prev[i][AcZ]);

    axisValue_double = (axisValue)*Acc_scaleFactor;

    if (accData[i] < axisValue_double)

      accData[i] = axisValue_double;

  }

}

/*

  Blynk data type

  Type     MIN             MAX

  Integer  -2,147,483,648  2,147,483,647

  Double   -1.8 x 10^300   4.9 x 10^-324

  String   any value is accepted

*/

uint32_t updateCount = 0;

void Timer1()

{

  Blynk.virtualWrite(0, accData[0]);

  Blynk.virtualWrite(1, accData[1]);

  Blynk.virtualWrite(2, accData[2]);

  Blynk.virtualWrite(3, accData[3]);

  Blynk.virtualWrite(4, soundData);

  memset(accData, 0, sizeof(accData)), soundData = 0;

  Serial.print(F("Updating data - ")), Serial.println(++updateCount);

}

bool led_state = false;

void Timer2()

{

  digitalWrite(17, led_state);

  if (led_state)

    led_state = false;

  else

    led_state = true;

}

void setup()

{

  GPIO_init();

  digitalWrite(17, HIGH);

  Serial.begin(9600);

  delay(1000);

  Wire.begin(); // I2C 통신 시작

  Wire.setClock(3400000UL);

  setupMPU(); // MPU6050 설정

  getMeasurement();

  Blynk.begin(BLYNK_AUTH_TOKEN, nbAccess, gprs, client, pin, "sgp1.blynk.cloud");

  Blynk.run();

  timer.setInterval(60000L, Timer1);

  timer.setInterval(500L, Timer2);

}

void loop()

{

  getMeasurement();

  if (Blynk.connected())

    Blynk.run();

  else

  {

    Serial.println("Lost connection");

    MODEM.hardReset();

    NVIC_SystemReset();

  }

  Serial.println(F("blynk.run"));

  timer.run();

}

Well, first of all this code won’t compile under Blynk 1/3.0 because these two lines arent at the very top of your sketch…

You should be calling getMeasurement(); from your void loop and personally I wouldn’t do an if (Blynk.connected()) test in your void loop if you’re using Blynk.begin().

You’re also doing some other strange stuff, like calling Blynk.run in void setup.

Pete.

[Screenshot removed by moderator]

That’s right. It won’t compile in version 1.3.0, but I did get a compile error code back that said it was a problem with a double-type variable, not a positional problem in the code you mentioned.

And did you happen to try running it on version 1.2.0?

So, how do I make sure this system is connected to the network properly?

This is because the getMeasurement function needs to perform as many iterations as possible in as little time as possible on the MCU.

I’m not sure what your screenshot is meant to show, but I’d suggest that you copy/paste the relevant text and post it with triple backticks at the beginning and end.

The error message relating to the positioning of the Template Name and ID will be:
#error "Please specify your BLYNK_TEMPLATE_ID and BLYNK_TEMPLATE_NAME

You’ve mentioned this twice, but haven’t shared the code that creates the compiler error message, or the details of the message itself.

That sounds like it’s not compatible with Blynk then.

Pete.

[Screenshot removed by moderator]

Will this illustration help you solve it?

In the code I sent you, the location of the #define is the original, unaltered code.

Can you suggest another way to do this?

No, but if you edit your post, delete the screenshot and post the relevant piece of code and the text of the compiler error message (both with triple backticks) then I’ll take a look at it.

Remove getMeasurement(); from your void loop and call it with a BlynkTimer.

Pete.

If you want something other than what’s below, you’ll need to tell us how to make it appear…

Processing mkrnb1500 (platform: atmelsam; board: mkrnb1500; framework: arduino)
-----------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelsam/mkrnb1500.html
PLATFORM: Atmel SAM (8.1.0) > Arduino MKR NB 1500
HARDWARE: SAMD21G18A 48MHz, 32KB RAM, 256KB Flash
DEBUG: Current (atmel-ice) External (atmel-ice, blackmagic, jlink)
PACKAGES: 
 - framework-arduino-samd @ 1.8.13
 - framework-cmsis @ 1.40500.0 (4.5.0)
 - framework-cmsis-atmel @ 1.2.2
 - toolchain-gccarmnoneeabi @ 1.70201.0 (7.2.1)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 17 compatible libraries
Scanning dependencies...
Dependency Graph
|-- Blynk @ 1.3.0
|-- MKRNB @ 1.5.1
|-- Wire @ 1.0
Building in release mode
Compiling .pio\build\mkrnb1500\src\main.cpp.o
Compiling .pio\build\mkrnb1500\lib74b\BlynkNcpDriver\BlynkRpcCRC8.c.o
Compiling .pio\build\mkrnb1500\lib74b\BlynkNcpDriver\BlynkRpcClientWeakImpl.c.o
Compiling .pio\build\mkrnb1500\lib74b\BlynkNcpDriver\BlynkRpcInfra.c.o
Compiling .pio\build\mkrnb1500\lib74b\BlynkNcpDriver\BlynkRpcInfraUart.c.o
Compiling .pio\build\mkrnb1500\lib74b\BlynkNcpDriver\BlynkRpcUartFraming.c.o
Compiling .pio\build\mkrnb1500\lib74b\BlynkNcpDriver\MessageBuffer.c.o
Compiling .pio\build\mkrnb1500\lib74b\BlynkNcpDriver\MessageWriter.c.o
Compiling .pio\build\mkrnb1500\libc78\MKRNB-1.5.1\GPRS.cpp.o
Compiling .pio\build\mkrnb1500\libc78\MKRNB-1.5.1\Modem.cpp.o
Compiling .pio\build\mkrnb1500\libc78\MKRNB-1.5.1\NB.cpp.o
Compiling .pio\build\mkrnb1500\libc78\MKRNB-1.5.1\NBClient.cpp.o
Compiling .pio\build\mkrnb1500\libc78\MKRNB-1.5.1\NBFileUtils.cpp.o
Compiling .pio\build\mkrnb1500\libc78\MKRNB-1.5.1\NBModem.cpp.o
Archiving .pio\build\mkrnb1500\lib74b\libBlynkNcpDriver.a
Compiling .pio\build\mkrnb1500\libc78\MKRNB-1.5.1\NBPIN.cpp.o
lib\MKRNB-1.5.1\src\NBFileUtils.cpp: In member function 'uint32_t NBFileUtils::downloadFile(arduino::String, const char*, uint32_t, bool)':
lib\MKRNB-1.5.1\src\NBFileUtils.cpp:117:28: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         for (auto i = 0; i < size; i++) {
                          ~~^~~~~~
lib\MKRNB-1.5.1\src\NBFileUtils.cpp: In member function 'uint32_t NBFileUtils::readFile(arduino::String, arduino::String*)':
lib\MKRNB-1.5.1\src\NBFileUtils.cpp:179:24: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for (auto i = 0; i < size; i++) {
                      ~~^~~~~~
lib\MKRNB-1.5.1\src\NBFileUtils.cpp: In member function 'uint32_t NBFileUtils::readFile(arduino::String, uint8_t*)':
lib\MKRNB-1.5.1\src\NBFileUtils.cpp:226:24: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for (auto i = 0; i < size; i++) {
                      ~~^~~~~~
lib\MKRNB-1.5.1\src\NBFileUtils.cpp: In member function 'uint32_t NBFileUtils::readBlock(arduino::String, uint32_t, uint32_t, uint8_t*)':
lib\MKRNB-1.5.1\src\NBFileUtils.cpp:273:24: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for (auto i = 0; i < size; i++) {
                      ~~^~~~~~
lib\MKRNB-1.5.1\src\NBFileUtils.cpp: In member function 'int NBFileUtils::deleteFiles()':      
lib\MKRNB-1.5.1\src\NBFileUtils.cpp:316:9: warning: unused variable 'num' [-Wunused-variable]  
     int num = listFiles(files);
         ^~~
Compiling .pio\build\mkrnb1500\libc78\MKRNB-1.5.1\NBSSLClient.cpp.o
Compiling .pio\build\mkrnb1500\libc78\MKRNB-1.5.1\NBScanner.cpp.o
Compiling .pio\build\mkrnb1500\libc78\MKRNB-1.5.1\NBUdp.cpp.o
Compiling .pio\build\mkrnb1500\libc78\MKRNB-1.5.1\NB_SMS.cpp.o
Compiling .pio\build\mkrnb1500\libc78\MKRNB-1.5.1\utility\NBSocketBuffer.cpp.o
Compiling .pio\build\mkrnb1500\lib25a\Blynk\utility\BlynkDebug.cpp.o
Compiling .pio\build\mkrnb1500\lib25a\Blynk\utility\BlynkHandlers.cpp.o
Compiling .pio\build\mkrnb1500\lib25a\Blynk\utility\BlynkHelpers.cpp.o
Compiling .pio\build\mkrnb1500\lib25a\Blynk\utility\BlynkTimeUtils.cpp.o
Compiling .pio\build\mkrnb1500\lib25a\Blynk\utility\BlynkTimer.cpp.o
Compiling .pio\build\mkrnb1500\lib25a\Blynk\utility\utility.cpp.o
Compiling .pio\build\mkrnb1500\libe79\Wire\Wire.cpp.o
Archiving .pio\build\mkrnb1500\libc78\libMKRNB-1.5.1.a
Compiling .pio\build\mkrnb1500\FrameworkArduinoVariant\variant.cpp.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\Reset.cpp.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\SERCOM.cpp.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\Tone.cpp.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\USB\CDC.cpp.o
Archiving .pio\build\mkrnb1500\libe79\libWire.a
Compiling .pio\build\mkrnb1500\FrameworkArduino\USB\USBCore.cpp.o
Archiving .pio\build\mkrnb1500\lib25a\libBlynk.a
Compiling .pio\build\mkrnb1500\FrameworkArduino\USB\samd21_host.c.o
Archiving .pio\build\mkrnb1500\libFrameworkArduinoVariant.a
Compiling .pio\build\mkrnb1500\FrameworkArduino\Uart.cpp.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\WInterrupts.c.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\WMath.cpp.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\abi.cpp.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\api\Common.cpp.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\api\IPAddress.cpp.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\api\PluggableUSB.cpp.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\api\Print.cpp.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\api\Stream.cpp.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\api\String.cpp.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\compact\dtostrf.c.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\cortex_handlers.c.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\delay.c.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\hooks.c.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\itoa.c.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\main.cpp.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\new.cpp.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\pulse.c.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\pulse_asm.S.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\startup.c.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\wiring.c.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\wiring_analog.c.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\wiring_digital.c.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\wiring_private.c.o
Compiling .pio\build\mkrnb1500\FrameworkArduino\wiring_shift.c.o
Archiving .pio\build\mkrnb1500\libFrameworkArduino.a
Linking .pio\build\mkrnb1500\firmware.elf
.pio\build\mkrnb1500\src\main.cpp.o: In function `void BlynkApi<BlynkProtocol<BlynkArduinoClientGen<arduino::Client> > >::virtualWrite<double>(int, double)':
main.cpp:(.text._ZN8BlynkApiI13BlynkProtocolI21BlynkArduinoClientGenIN7arduino6ClientEEEE12virtualWriteIJdEEEviDpT_[_ZN8BlynkApiI13BlynkProtocolI21BlynkArduinoClientGenIN7arduino6ClientEEEE12virtualWriteIJdEEEviDpT_]+0x38): undefined reference to `dtostrf_internal(double, signed char, unsigned char, char*)'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\mkrnb1500\firmware.elf] Error 1
================================= [FAILED] Took 4.86 seconds =================================

 *  터미널 프로세스 "C:\Users\k3492\.platformio\penv\Scripts\platformio.exe 'run', '--environment', 'mkrnb1500'"이(가) 종료되었습니다(종료 코드: 1). 
 *  터미널이 작업에서 다시 사용됩니다. 닫으려면 아무 키나 누르세요. 

Oh, and why does the blynk.run() function keep getting stuck in an infinite loop?

I still have no idea which line of code in your sketch is making this error message appear, despite asking for it multiple times.

I also have no idea if you’ve moved #define BLYNK_TEMPLATE_ID "TMPL6lM3nJxMN" and #define BLYNK_TEMPLATE_NAME "Expansion Joint" to the top of your sketch, as is required with all versions of the Blynk library except 1.2.0.

When you use Blynk.begin() it’s a blocking function, which may be the cause of your issue, but you’ve not really explained what the symptoms of your “infinite loop” are, and what you see in your serial monitor when this happens.

And, if you’re asked to EDIT an existing post, then please do that, rather than leaving the post unedited and re-posting the requested data in a new post.

Pete.

We are very sorry for the hassle.

This syntax only causes problems when the variable type you are writing to is a double.
If you remove that syntax and try to write a variable of type int, there is no problem.

  Blynk.virtualWrite(0, accData[0]);

  Blynk.virtualWrite(1, accData[1]);

  Blynk.virtualWrite(2, accData[2]);

  Blynk.virtualWrite(3, accData[3]);

Yes, since you mentioned it, it has been moved to the top line of the code.

After about two hours of running in the code I sent you, the
Serial.println(F(“blynk.run”)) the syntax doesn’t print and the Arduino freezes.
The LEDs stop flashing, and the cloud connection is lost.

What is executed above that statement is blynk.begin.

What happens if you try a simple test like this…

double test =  123.456;
Blynk.virtualWrite(V0, test);

Did you try what I suggested and remove this:

and replace it with Blynk.run(); ?

Have you tried moving this out of your void loop…

and calling it with a BlynkTimer instead?

Pete.

This didn’t work in 1.3.0 either…
I’m going to go with 1.2.0 for now.

Based on everything you’ve said, I’ve modified the code.

The getMeasurement() function was taking about 4-5ms, so I modified the code by adding 10ms to the timer.

#include <Arduino.h>
#include <Wire.h> // I2C 통신과 관련된 라이브러리
// Blynk 장치 ID
#define DEVICE_ID 2
// Blynk 설정
#define BLYNK_TEMPLATE_ID "TMPL6lM3nJxMN"
#define BLYNK_TEMPLATE_NAME "Expansion Joint"
const char *BLYNK_AUTH_TOKENS[] = {
"",
"DlcXosJtli9mCLRVaUpZmC86vM_9Z4Qk",
"F0X8EnEl6ZDZ9jGttffSPj9kOGFYkGVU"};
#define BLYNK_AUTH_TOKEN (BLYNK_AUTH_TOKENS[DEVICE_ID])
#include <MKRNB.h>            // MKR NB 보드와 관련된 라이브러리
#include <BlynkSimpleMKRNB.h> // MKR NB 보드용 Blynk 라이브러리

// MKR NB 초기화
NBClient client;
GPRS gprs;
NB nbAccess;
BlynkTimer timer;

char pin[] = "0000";

/*  GPIO
포트 핀 구성

아두이노 포트 핀 기능: pinMode(), digitalRead() 및 digitalWrite()는 기본적으로 어쨌든 이 작업을 수행합니다.
digitalRead() 및 digitalWrite()에 비해 직접 레지스터 조작을 사용하면 약간의 성능 이점만 있습니다.

포트 핀 입력

특정 포트 핀을 입력으로 설정하려면:
PORT->Group[PORTA].PINCFG[19].bit.INEN = 1;  // Enable PA19 input
PORT->Group[PORTA].PINCFG[19].bit.PULLEN = 0;
PORT->Group[PORTA].DIRCLR.reg = PORT_PA19;

풀업 저항으로 입력을 활성화하려면:
PORT->Group[PORTA].PINCFG[19].bit.INEN = 1;  // Enable PA19 input with a pull-up resistor
PORT->Group[PORTA].PINCFG[19].bit.PULLEN = 1;
PORT->Group[PORTA].DIRCLR.reg = PORT_PA19;
PORT->Group[PORTA].OUTSET.reg = PORT_PA19;

풀다운 저항으로 입력을 활성화하려면:
PORT->Group[PORTA].PINCFG[19].bit.INEN = 1;  // Enable PA19 input with a pull-down resistor
PORT->Group[PORTA].PINCFG[19].bit.PULLEN = 1;
PORT->Group[PORTA].DIRCLR.reg = PORT_PA19;
PORT->Group[PORTA].OUTCLR.reg = PORT_PA19;

입력을 읽으려면:
if (PORT->Group[PORTA].IN.reg & PORT_PA19)  // Read the input pin on PA19

포트 핀 출력

특정 포트 핀을 출력으로 설정하려면:
PORT->Group[PORTA].DIRSET.reg = PORT_PA19;  // Set PA19 to an output
PORT->Group[PORTA].PINCFG[19].bit.INEN = 1;  // Support output read back

출력을 높게 설정하려면:
PORT->Group[PORTA].OUTSET.reg = PORT_PA19;  // Set PA19 output HIGH

출력을 낮게 설정하려면:
PORT->Group[PORTA].OUTCLR.reg = PORT_PA19;  // Set PA19 output LOW

Arduino-포트 핀 매핑

예를 들어 디지털 핀 D12의 경우 Arduino "g_APinDescription" 구조를 사용하여 Arduino 핀 번호에서 포트 핀으로 매핑하는 것도 가능합니다.

PORT->Group[g_APinDescription[12].ulPort].PINCFG[g_APinDescription[12].ulPin].bit.INEN = 1;
*/
void GPIO_init()
{
  pinMode(17, OUTPUT);

  analogReadResolution(12);

  // analogReference(AR_DEFAULT) = Set the analogue input threshold to 3.3V
  ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_DIV2_Val;
  ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val;

  // pinMode(A2, OUTPUT);
  PORT->Group[PORTB].DIRSET.reg = PORT_PB03;
  PORT->Group[PORTB].PINCFG[3].bit.INEN = 1;
  // pinMode(D0, INPUT);
  PORT->Group[PORTA].PINCFG[22].bit.INEN = 1;
  PORT->Group[PORTA].PINCFG[22].bit.PULLEN = 0;
  PORT->Group[PORTA].DIRCLR.reg = PORT_PA22;
  // pinMode(D1, OUTPUT);
  PORT->Group[PORTA].DIRSET.reg = PORT_PA23;
  PORT->Group[PORTA].PINCFG[23].bit.INEN = 1;
  // pinMode(D2, INPUT);
  PORT->Group[PORTA].PINCFG[10].bit.INEN = 1;
  PORT->Group[PORTA].PINCFG[10].bit.PULLEN = 0;
  PORT->Group[PORTA].DIRCLR.reg = PORT_PA10;
  // pinMode(D3, OUTPUT);
  PORT->Group[PORTA].DIRSET.reg = PORT_PA11;
  PORT->Group[PORTA].PINCFG[11].bit.INEN = 1;
  // pinMode(D4, INPUT);
  PORT->Group[PORTB].PINCFG[10].bit.INEN = 1;
  PORT->Group[PORTB].PINCFG[10].bit.PULLEN = 0;
  PORT->Group[PORTB].DIRCLR.reg = PORT_PB10;
  // pinMode(D5, OUTPUT);
  PORT->Group[PORTB].DIRSET.reg = PORT_PB11;
  PORT->Group[PORTB].PINCFG[11].bit.INEN = 1;
  // pinMode(D6, INPUT);
  PORT->Group[PORTA].PINCFG[20].bit.INEN = 1;
  PORT->Group[PORTA].PINCFG[20].bit.PULLEN = 0;
  PORT->Group[PORTA].DIRCLR.reg = PORT_PA20;
  // pinMode(D7, OUTPUT);
  PORT->Group[PORTA].DIRSET.reg = PORT_PA21;
  PORT->Group[PORTA].PINCFG[21].bit.INEN = 1;
}

// MPU6050 변수
float Acc_scaleFactor, Gyro_scaleFactor;
const int8_t MPU_ADDR = 0x69;
// mpuData 인덱스 열거형
enum SensorIndex
{
  AcX,
  AcY,
  AcZ,
  Tmp,
  GyX,
  GyY,
  GyZ
};
// MPU6050 레지스터를 설정하는 함수
inline void configureMPURegister(int8_t registerAddr, int8_t value)
{
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(registerAddr);
  Wire.write(value);
  Wire.endTransmission(true);
}

void setupMPU()
{
  // MPU6050 전체(4개) 활성화
  PORT->Group[PORTA].OUTSET.reg = PORT_PA23;
  PORT->Group[PORTA].OUTSET.reg = PORT_PA11;
  PORT->Group[PORTB].OUTSET.reg = PORT_PB11;
  PORT->Group[PORTA].OUTSET.reg = PORT_PA21;

  // MPU6050 초기화 및 리셋
  configureMPURegister(0x6B, 0);    // MPU-6050 활성화
  configureMPURegister(0x6B, 0x03); // 클럭 소스 설정

  /*  가속도계 설정
AFS_SEL=0, Full Scale Range = +/- 2 [g]
AFS_SEL=1, Full Scale Range = +/- 4 [g]
AFS_SEL=2, Full Scale Range = +/- 8 [g]
AFS_SEL=3, Full Scale Range = +/- 10 [g]
  */
  switch (0)
  {
  case 0:
configureMPURegister(0x1C, 0x00);
Acc_scaleFactor = 16384;
break;
  case 1:
configureMPURegister(0x1C, 0x08);
Acc_scaleFactor = 8192;
break;
  case 2:
configureMPURegister(0x1C, 0x10);
Acc_scaleFactor = 4096;
break;
  default:
configureMPURegister(0x1C, 0x18);
Acc_scaleFactor = 3276.8;
break;
  }
  // 스케일 팩터를 역수로 취함
  Acc_scaleFactor = 1.0 / Acc_scaleFactor;

  /*  자이로스코프 설정
FS_SEL=0, Full Scale Range = +/- 250 [degree/sec]
FS_SEL=1, Full Scale Range = +/- 500 [degree/sec]
FS_SEL=2, Full Scale Range = +/- 1000 [degree/sec]
FS_SEL=3, Full Scale Range = +/- 2000 [degree/sec]
  */
  switch (0)
  {
  case 0:
configureMPURegister(0x1B, 0x00);
Gyro_scaleFactor = 1.0 / 131.0;
break;
  case 1:
configureMPURegister(0x1B, 0x08);
Gyro_scaleFactor = 65.5;
break;
  case 2:
configureMPURegister(0x1B, 0x10);
Gyro_scaleFactor = 32.8;
break;
  default:
configureMPURegister(0x1B, 0x18);
Gyro_scaleFactor = 16.4;
break;
  }
  // 스케일 팩터를 역수로 취함
  Gyro_scaleFactor = 1.0 / Gyro_scaleFactor;

  /*  DLPF 설정
Accel BW 260Hz, Delay    0ms / Gyro BW 256Hz, Delay 0.98ms, Fs 8KHz
Accel BW 184Hz, Delay    2ms / Gyro BW 188Hz, Delay  1.9ms, Fs 1KHz
Accel BW  94Hz, Delay    3ms / Gyro BW  98Hz, Delay  2.8ms, Fs 1KHz
Accel BW  44Hz, Delay  4.9ms / Gyro BW  42Hz, Delay  4.8ms, Fs 1KHz
Accel BW  21Hz, Delay  8.5ms / Gyro BW  20Hz, Delay  8.3ms, Fs 1KHz
Accel BW  10Hz, Delay 13.8ms / Gyro BW  10Hz, Delay 13.4ms, Fs 1KHz
Accel BW   5Hz, Delay   19ms / Gyro BW   5Hz, Delay 18.6ms, Fs 1KHz
  */
  configureMPURegister(0x1A, 6);

  // MPU6050 전체(4개) 비활성화
  PORT->Group[PORTA].OUTCLR.reg = PORT_PA23;
  PORT->Group[PORTA].OUTCLR.reg = PORT_PA11;
  PORT->Group[PORTB].OUTCLR.reg = PORT_PB11;
  PORT->Group[PORTA].OUTCLR.reg = PORT_PA21;
}

// 배열 크기 수정요함 (타입, 크기)
int16_t mpuData[4][7];      // [0,1,2,3][AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ] 순으로 저장
int32_t mpuData_prev[4][3]; // [num][data]
const uint8_t MPU_portGroup[4] = {0, 0, 1, 0};
const uint32_t MPU_writePin[4] = {1ul << 23, 1ul << 11, 1ul << 11, 1ul << 21};
const uint32_t MPU_readPin[4] = {1ul << 22, 1ul << 10, 1ul << 10, 1ul << 20};
// MPU6050에서 데이터 읽기
inline void readMPU(uint8_t MPU_num)
{
  // Data Backup
  mpuData_prev[MPU_num][AcX] = mpuData[MPU_num][AcX];
  mpuData_prev[MPU_num][AcY] = mpuData[MPU_num][AcY];
  mpuData_prev[MPU_num][AcZ] = mpuData[MPU_num][AcZ];

  // 해당 핀이 활성화되어 있으면, 무시
  if (PORT->Group[MPU_portGroup[MPU_num]].IN.reg & MPU_readPin[MPU_num])
return;

  // 해당 핀이 비활성화되어 있으면, MPU 활성화
  else
PORT->Group[MPU_portGroup[MPU_num]].OUTSET.reg = MPU_writePin[MPU_num];

  // 데이터 읽기
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(0x3B);
  Wire.endTransmission(false);

  // 가속도 데이터만 호출
  Wire.requestFrom(MPU_ADDR, 6, true); // 2byte * 3
  mpuData[MPU_num][AcX] = (Wire.read() << 8 | Wire.read());
  mpuData[MPU_num][AcY] = (Wire.read() << 8 | Wire.read());
  mpuData[MPU_num][AcZ] = (Wire.read() << 8 | Wire.read());

  // MPU 비활성화
  PORT->Group[MPU_portGroup[MPU_num]].OUTCLR.reg = MPU_writePin[MPU_num];
}

double accData[4] = {0.0, 0.0, 0.0, 0.0};
int accData_lengh = sizeof(accData);
uint32_t soundData = 0;
inline void Get_measurement()
{
  // 소음 측정
  uint32_t soundValue = analogRead(A0);
  if (soundData < soundValue)
soundData = soundValue;

  // 진동 측정
  uint32_t axisValue;
  double axisValue_double;
  for (int i = 0; i < 4; i++)
  {
readMPU(i);

axisValue = abs(mpuData[i][AcX] - mpuData_prev[i][AcX]);
axisValue += abs(mpuData[i][AcY] - mpuData_prev[i][AcY]);
axisValue += abs(mpuData[i][AcZ] - mpuData_prev[i][AcZ]);

axisValue_double = (axisValue)*Acc_scaleFactor;

if (accData[i] < axisValue_double)
  accData[i] = axisValue_double;
  }
}

/*
  Blynk data type
  Type     MIN             MAX
  Integer  -2,147,483,648  2,147,483,647
  Double   -1.8 x 10^300   4.9 x 10^-324
  String   any value is accepted
*/
uint32_t updateCount = 0;
void Cloud_update()
{
  Blynk.virtualWrite(0, accData[0]);
  Blynk.virtualWrite(1, accData[1]);
  Blynk.virtualWrite(2, accData[2]);
  Blynk.virtualWrite(3, accData[3]);
  Blynk.virtualWrite(4, soundData);
  memset(accData, 0, accData_lengh), soundData = 0;
  Serial.print(F("Updating data - ")), Serial.println(++updateCount);
}

bool led_state = false;
void LED_blink()
{
  digitalWrite(17, led_state);
  if (led_state)
led_state = false;
  else
led_state = true;
}

void setup()
{
  GPIO_init();
  digitalWrite(17, HIGH);

  Serial.begin(9600);
  delay(1000);

  Wire.begin(); // I2C 통신 시작
  Wire.setClock(3400000UL);

  setupMPU(); // MPU6050 설정
  Get_measurement();

  Blynk.begin(BLYNK_AUTH_TOKEN, nbAccess, gprs, client, pin, "sgp1.blynk.cloud");
  Blynk.run();

  timer.setInterval(60000L, Cloud_update);
  timer.setInterval(500L, LED_blink);
  timer.setInterval(10L, Get_measurement);
}

void loop()
{
  Blynk.run();
  /*
  {
Serial.println("Lost connection");
MODEM.hardReset();
NVIC_SystemReset();
  }
  */
  timer.run();
}

I’m going to leave it on for the day to see if it freezes like it did before.

hello.

I’m working on an arduino mkr nb 1500 to monitor sensor data on platform.io.

I modified the code as per your help yesterday and have been testing it for a day or so, but the arduino freezes after about 10-30 minutes.

The code is shown below.
We’ve temporarily removed the blynk-specific #define.

#include <Arduino.h>

#include <Wire.h> // I2C 통신과 관련된 라이브러리

// Blynk 장치 ID

#define DEVICE_ID 2

// Blynk 설정

#define BLYNK_TEMPLATE_ID "="

#define BLYNK_TEMPLATE_NAME "="

const char *BLYNK_AUTH_TOKENS[] = {

    "",

    "=",

    "="};

#define BLYNK_AUTH_TOKEN (BLYNK_AUTH_TOKENS[DEVICE_ID])

#include <MKRNB.h>            // MKR NB 보드와 관련된 라이브러리

#include <BlynkSimpleMKRNB.h> // MKR NB 보드용 Blynk 라이브러리

// MKR NB 초기화

NBClient client;

GPRS gprs;

NB nbAccess;

BlynkTimer timer;

char pin[] = "0000";

/*  GPIO

포트 핀 구성

아두이노 포트 핀 기능: pinMode(), digitalRead() 및 digitalWrite()는 기본적으로 어쨌든 이 작업을 수행합니다.

digitalRead() 및 digitalWrite()에 비해 직접 레지스터 조작을 사용하면 약간의 성능 이점만 있습니다.

포트 핀 입력

특정 포트 핀을 입력으로 설정하려면:

PORT->Group[PORTA].PINCFG[19].bit.INEN = 1;  // Enable PA19 input

PORT->Group[PORTA].PINCFG[19].bit.PULLEN = 0;

PORT->Group[PORTA].DIRCLR.reg = PORT_PA19;

풀업 저항으로 입력을 활성화하려면:

PORT->Group[PORTA].PINCFG[19].bit.INEN = 1;  // Enable PA19 input with a pull-up resistor

PORT->Group[PORTA].PINCFG[19].bit.PULLEN = 1;

PORT->Group[PORTA].DIRCLR.reg = PORT_PA19;

PORT->Group[PORTA].OUTSET.reg = PORT_PA19;

풀다운 저항으로 입력을 활성화하려면:

PORT->Group[PORTA].PINCFG[19].bit.INEN = 1;  // Enable PA19 input with a pull-down resistor

PORT->Group[PORTA].PINCFG[19].bit.PULLEN = 1;

PORT->Group[PORTA].DIRCLR.reg = PORT_PA19;

PORT->Group[PORTA].OUTCLR.reg = PORT_PA19;

입력을 읽으려면:

if (PORT->Group[PORTA].IN.reg & PORT_PA19)  // Read the input pin on PA19

포트 핀 출력

특정 포트 핀을 출력으로 설정하려면:

PORT->Group[PORTA].DIRSET.reg = PORT_PA19;  // Set PA19 to an output

PORT->Group[PORTA].PINCFG[19].bit.INEN = 1;  // Support output read back

출력을 높게 설정하려면:

PORT->Group[PORTA].OUTSET.reg = PORT_PA19;  // Set PA19 output HIGH

출력을 낮게 설정하려면:

PORT->Group[PORTA].OUTCLR.reg = PORT_PA19;  // Set PA19 output LOW

Arduino-포트 핀 매핑

예를 들어 디지털 핀 D12의 경우 Arduino "g_APinDescription" 구조를 사용하여 Arduino 핀 번호에서 포트 핀으로 매핑하는 것도 가능합니다.

PORT->Group[g_APinDescription[12].ulPort].PINCFG[g_APinDescription[12].ulPin].bit.INEN = 1;

*/

void GPIO_init()

{

  pinMode(17, OUTPUT);

  analogReadResolution(12);

  // analogReference(AR_DEFAULT) = Set the analogue input threshold to 3.3V

  ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_DIV2_Val;

  ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val;

  // pinMode(A2, OUTPUT);

  PORT->Group[PORTB].DIRSET.reg = PORT_PB03;

  PORT->Group[PORTB].PINCFG[3].bit.INEN = 1;

  // pinMode(D0, INPUT);

  PORT->Group[PORTA].PINCFG[22].bit.INEN = 1;

  PORT->Group[PORTA].PINCFG[22].bit.PULLEN = 0;

  PORT->Group[PORTA].DIRCLR.reg = PORT_PA22;

  // pinMode(D1, OUTPUT);

  PORT->Group[PORTA].DIRSET.reg = PORT_PA23;

  PORT->Group[PORTA].PINCFG[23].bit.INEN = 1;

  // pinMode(D2, INPUT);

  PORT->Group[PORTA].PINCFG[10].bit.INEN = 1;

  PORT->Group[PORTA].PINCFG[10].bit.PULLEN = 0;

  PORT->Group[PORTA].DIRCLR.reg = PORT_PA10;

  // pinMode(D3, OUTPUT);

  PORT->Group[PORTA].DIRSET.reg = PORT_PA11;

  PORT->Group[PORTA].PINCFG[11].bit.INEN = 1;

  // pinMode(D4, INPUT);

  PORT->Group[PORTB].PINCFG[10].bit.INEN = 1;

  PORT->Group[PORTB].PINCFG[10].bit.PULLEN = 0;

  PORT->Group[PORTB].DIRCLR.reg = PORT_PB10;

  // pinMode(D5, OUTPUT);

  PORT->Group[PORTB].DIRSET.reg = PORT_PB11;

  PORT->Group[PORTB].PINCFG[11].bit.INEN = 1;

  // pinMode(D6, INPUT);

  PORT->Group[PORTA].PINCFG[20].bit.INEN = 1;

  PORT->Group[PORTA].PINCFG[20].bit.PULLEN = 0;

  PORT->Group[PORTA].DIRCLR.reg = PORT_PA20;

  // pinMode(D7, OUTPUT);

  PORT->Group[PORTA].DIRSET.reg = PORT_PA21;

  PORT->Group[PORTA].PINCFG[21].bit.INEN = 1;

}

// MPU6050 변수

float Acc_scaleFactor, Gyro_scaleFactor;

const int8_t MPU_ADDR = 0x69;

// mpuData 인덱스 열거형

enum SensorIndex

{

  AcX,

  AcY,

  AcZ,

  Tmp,

  GyX,

  GyY,

  GyZ

};

// MPU6050 레지스터를 설정하는 함수

inline void configureMPURegister(int8_t registerAddr, int8_t value)

{

  Wire.beginTransmission(MPU_ADDR);

  Wire.write(registerAddr);

  Wire.write(value);

  Wire.endTransmission(true);

}

void setupMPU()

{

  // MPU6050 전체(4개) 활성화

  PORT->Group[PORTA].OUTSET.reg = PORT_PA23;

  PORT->Group[PORTA].OUTSET.reg = PORT_PA11;

  PORT->Group[PORTB].OUTSET.reg = PORT_PB11;

  PORT->Group[PORTA].OUTSET.reg = PORT_PA21;

  // MPU6050 초기화 및 리셋

  configureMPURegister(0x6B, 0);    // MPU-6050 활성화

  configureMPURegister(0x6B, 0x03); // 클럭 소스 설정

  /*  가속도계 설정

    AFS_SEL=0, Full Scale Range = +/- 2 [g]

    AFS_SEL=1, Full Scale Range = +/- 4 [g]

    AFS_SEL=2, Full Scale Range = +/- 8 [g]

    AFS_SEL=3, Full Scale Range = +/- 10 [g]

  */

  switch (0)

  {

  case 0:

    configureMPURegister(0x1C, 0x00);

    Acc_scaleFactor = 16384;

    break;

  case 1:

    configureMPURegister(0x1C, 0x08);

    Acc_scaleFactor = 8192;

    break;

  case 2:

    configureMPURegister(0x1C, 0x10);

    Acc_scaleFactor = 4096;

    break;

  default:

    configureMPURegister(0x1C, 0x18);

    Acc_scaleFactor = 3276.8;

    break;

  }

  // 스케일 팩터를 역수로 취함

  Acc_scaleFactor = 1.0 / Acc_scaleFactor;

  /*  자이로스코프 설정

    FS_SEL=0, Full Scale Range = +/- 250 [degree/sec]

    FS_SEL=1, Full Scale Range = +/- 500 [degree/sec]

    FS_SEL=2, Full Scale Range = +/- 1000 [degree/sec]

    FS_SEL=3, Full Scale Range = +/- 2000 [degree/sec]

  */

  switch (0)

  {

  case 0:

    configureMPURegister(0x1B, 0x00);

    Gyro_scaleFactor = 1.0 / 131.0;

    break;

  case 1:

    configureMPURegister(0x1B, 0x08);

    Gyro_scaleFactor = 65.5;

    break;

  case 2:

    configureMPURegister(0x1B, 0x10);

    Gyro_scaleFactor = 32.8;

    break;

  default:

    configureMPURegister(0x1B, 0x18);

    Gyro_scaleFactor = 16.4;

    break;

  }

  // 스케일 팩터를 역수로 취함

  Gyro_scaleFactor = 1.0 / Gyro_scaleFactor;

  /*  DLPF 설정

    Accel BW 260Hz, Delay    0ms / Gyro BW 256Hz, Delay 0.98ms, Fs 8KHz

    Accel BW 184Hz, Delay    2ms / Gyro BW 188Hz, Delay  1.9ms, Fs 1KHz

    Accel BW  94Hz, Delay    3ms / Gyro BW  98Hz, Delay  2.8ms, Fs 1KHz

    Accel BW  44Hz, Delay  4.9ms / Gyro BW  42Hz, Delay  4.8ms, Fs 1KHz

    Accel BW  21Hz, Delay  8.5ms / Gyro BW  20Hz, Delay  8.3ms, Fs 1KHz

    Accel BW  10Hz, Delay 13.8ms / Gyro BW  10Hz, Delay 13.4ms, Fs 1KHz

    Accel BW   5Hz, Delay   19ms / Gyro BW   5Hz, Delay 18.6ms, Fs 1KHz

  */

  configureMPURegister(0x1A, 6);

  // MPU6050 전체(4개) 비활성화

  PORT->Group[PORTA].OUTCLR.reg = PORT_PA23;

  PORT->Group[PORTA].OUTCLR.reg = PORT_PA11;

  PORT->Group[PORTB].OUTCLR.reg = PORT_PB11;

  PORT->Group[PORTA].OUTCLR.reg = PORT_PA21;

}

// 배열 크기 수정요함 (타입, 크기)

int16_t mpuData[4][7];      // [0,1,2,3][AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ] 순으로 저장

int32_t mpuData_prev[4][3]; // [num][data]

const uint8_t MPU_portGroup[4] = {0, 0, 1, 0};

const uint32_t MPU_writePin[4] = {1ul << 23, 1ul << 11, 1ul << 11, 1ul << 21};

const uint32_t MPU_readPin[4] = {1ul << 22, 1ul << 10, 1ul << 10, 1ul << 20};

// MPU6050에서 데이터 읽기

inline void readMPU(uint8_t MPU_num)

{

  // Data Backup

  mpuData_prev[MPU_num][AcX] = mpuData[MPU_num][AcX];

  mpuData_prev[MPU_num][AcY] = mpuData[MPU_num][AcY];

  mpuData_prev[MPU_num][AcZ] = mpuData[MPU_num][AcZ];

  // 해당 핀이 활성화되어 있으면, 무시

  if (PORT->Group[MPU_portGroup[MPU_num]].IN.reg & MPU_readPin[MPU_num])

    return;

  // 해당 핀이 비활성화되어 있으면, MPU 활성화

  else

    PORT->Group[MPU_portGroup[MPU_num]].OUTSET.reg = MPU_writePin[MPU_num];

  // 데이터 읽기

  Wire.beginTransmission(MPU_ADDR);

  Wire.write(0x3B);

  Wire.endTransmission(false);

  // 가속도 데이터만 호출

  Wire.requestFrom(MPU_ADDR, 6, true); // 2byte * 3

  mpuData[MPU_num][AcX] = (Wire.read() << 8 | Wire.read());

  mpuData[MPU_num][AcY] = (Wire.read() << 8 | Wire.read());

  mpuData[MPU_num][AcZ] = (Wire.read() << 8 | Wire.read());

  // MPU 비활성화

  PORT->Group[MPU_portGroup[MPU_num]].OUTCLR.reg = MPU_writePin[MPU_num];

}

double accData[4] = {0.0, 0.0, 0.0, 0.0};

int accData_lengh = sizeof(accData);

uint32_t soundData = 0;

uint32_t axisValue;

double axisValue_double;

inline void Get_measurement()

{

  // 소음 측정

  uint32_t soundValue = analogRead(A0);

  if (soundData < soundValue)

    soundData = soundValue;

  // 진동 측정

  for (int i = 0; i < 4; i++)

  {

    readMPU(i);

    axisValue = abs(mpuData[i][AcX] - mpuData_prev[i][AcX]) + abs(mpuData[i][AcY] - mpuData_prev[i][AcY]) + abs(mpuData[i][AcZ] - mpuData_prev[i][AcZ]);

    axisValue_double = (axisValue)*Acc_scaleFactor;

    if (accData[i] < axisValue_double)

      accData[i] = axisValue_double;

  }

}

/*

  Blynk data type

  Type     MIN             MAX

  Integer  -2,147,483,648  2,147,483,647

  Double   -1.8 x 10^300   4.9 x 10^-324

  String   any value is accepted

*/

uint32_t updateCount = 0;

void Cloud_update()

{

  Blynk.virtualWrite(0, accData[0]);

  Blynk.virtualWrite(1, accData[1]);

  Blynk.virtualWrite(2, accData[2]);

  Blynk.virtualWrite(3, accData[3]);

  Blynk.virtualWrite(4, soundData);

  memset(accData, 0, accData_lengh), soundData = 0;

  Serial.print(F("Updating data - ")), Serial.println(++updateCount);

}

bool led_state = false;

void LED_blink()

{

  digitalWrite(17, led_state);

  if (led_state)

    led_state = false;

  else

    led_state = true;

}

void setup()

{

  GPIO_init();

  digitalWrite(17, HIGH);

  Serial.begin(9600);

  delay(1000);

  Wire.begin(); // I2C 통신 시작

  Wire.setClock(3400000UL);

  setupMPU(); // MPU6050 설정

  readMPU(0), readMPU(1), readMPU(2), readMPU(3);

  readMPU(0), readMPU(1), readMPU(2), readMPU(3);

  Blynk.begin(BLYNK_AUTH_TOKEN, nbAccess, gprs, client, pin, "sgp1.blynk.cloud");

  Blynk.run();

  timer.setInterval(10L, Get_measurement);

  timer.setInterval(500L, LED_blink);

  timer.setInterval(60000L, Cloud_update);

}

void loop()

{

  Blynk.run();

  timer.run();

}

The monitor output looks like this

---- Opened the serial port COM3 ----
Updating data - 2
Updating data - 3
Updating data - 4
Updating data - 5
Updating data - 6
Updating data - 7
Updating data - 8
Updating data - 9
Updating data - 10
Updating data - 11
Updating data - 12
Updating data - 13
Updating data - 14
Updating data - 15
Updating data - 16
Updating data - 17
Updating data - 18
Updating data - 19
Updating data - 20
Updating data - 21
Updating data - 22
Updating data - 23
Updating data - 24
Updating data - 25
Updating data - 26
Updating data - 27
Updating data - 28
Updating data - 29
---- Closed serial port COM3 due to disconnection from the machine ----
---- Reopened serial port COM3 ----
Updating data - 1
Updating data - 2
Updating data - 3
Updating data - 4
Updating data - 5
Updating data - 6
Updating data - 7
---- Closed serial port COM3 due to disconnection from the machine ----
---- Reopened serial port COM3 ----
Updating data - 1
Updating data - 2
Updating data - 3
Updating data - 4
Updating data - 5
Updating data - 6
Updating data - 7
Updating data - 8
Updating data - 9
Updating data - 10
Updating data - 11
Updating data - 12
Updating data - 13
Updating data - 14
Updating data - 15
Updating data - 16
Updating data - 17
Updating data - 18
Updating data - 19
Updating data - 20
Updating data - 21
Updating data - 22
Updating data - 23
Updating data - 24
Updating data - 25
Updating data - 26
Updating data - 27
Updating data - 28
Updating data - 29
---- Closed serial port COM3 due to disconnection from the machine ----
    ---- Reopened serial port COM3 ----
    Updating data - 1
    Updating data - 2
    Updating data - 3
    Updating data - 4
    Updating data - 5
    Updating data - 6
    Updating data - 7
    Updating data - 8
    Updating data - 9
    Updating data - 10
    Updating data - 11
    Updating data - 12
    Updating data - 13
    Updating data - 14
    Updating data - 15
    Updating data - 16
    Updating data - 17
    Updating data - 18
    Updating data - 19
    Updating data - 20
    Updating data - 21
    ---- Closed serial port COM3 due to disconnection from the machine ----

I’ve done some testing and it seems that the blynk.run function gets stuck in an infinite loop.

I’m using lte cat.m1, what could be the problem?

@junsang I’ve moved your latest post into this topic, as it’s about the same subject.
Please don’t create new topics about the same thing, it makes it much harder for community members to follow the conversation thread.

What exactly does this mean?

Why have you moved your Template ID and Template Name so that they are no longer at the top of your sketch?

Have you tried testing using a far simpler sketch, to see if that helps with your connectivity issues?

Pete.

Suddenly, it occurred to me that someone might use my token, so I did.
It is only temporarily hidden before uploading the post

I tried very simply using blynk.begin and blynk.run and uploading random numbers to the cloud with a timer, but the connection was lost.

I tried to install the sensor, but my Arduino frequently got stuck in an infinite loop and lost connection to the cloud, so I added an MCU to reboot the RST pin.

However, I think this is very inefficient in many ways.

So you’ve redacted some of your sensitive data.
Personally, I tend to do this…

#define BLYNK_TEMPLATE_ID "REDACTED"
#define BLYNK_TEMPLATE_NAME "REDACTED"
#define BLYNK_AUTH_TOKEN "REDACTED"

It would make sense to post that sketch, and use it for the basis of future tests.

Pete.

The code below.
With this code, it worked for a bit longer and then broke.
About an hour or two?

#include <Arduino.h>

#include <Wire.h> // I2C 통신과 관련된 라이브러리

// Blynk 장치 ID

#define DEVICE_ID 2

// Blynk 설정

#define BLYNK_TEMPLATE_ID "TMPL6lM3nJxMN"

#define BLYNK_TEMPLATE_NAME "Expansion Joint"

const char *BLYNK_AUTH_TOKENS[] = {

    "",

    "DlcXosJtli9mCLRVaUpZmC86vM_9Z4Qk",

    "F0X8EnEl6ZDZ9jGttffSPj9kOGFYkGVU"};

#define BLYNK_AUTH_TOKEN (BLYNK_AUTH_TOKENS[DEVICE_ID])

#include <MKRNB.h>            // MKR NB 보드와 관련된 라이브러리

#include <BlynkSimpleMKRNB.h> // MKR NB 보드용 Blynk 라이브러리

// MKR NB 초기화

NBClient client;

GPRS gprs;

NB nbAccess;

BlynkTimer timer;

char pin[] = "0000";

void Cloud_update()

{

    long randNumber = random(300);

    Blynk.virtualWrite(0, randNumber);

}

void setup()

{

    Serial.begin(9600);

    delay(1000);

    MODEM.hardReset();

    Blynk.begin(BLYNK_AUTH_TOKEN, nbAccess, gprs, client, pin, "sgp1.blynk.cloud");

    Blynk.run();

    timer.setInterval(60000L, Cloud_update);

}

void loop()

{

    Blynk.run();

    timer.run();

}

I suspect that the answer to your issue is going to be to stop using the blocking Blynk.begin command, and instead to do the following:

  1. establish a GSM connection
  2. use the Blynk.config(GSM_object, auth_token, Blynk_server, port) command
  3. use Blynk.connect(optional_timeout_in_ms) to establish your Blynk connection
  4. only execute Blynk.run() if Blynk.connected == true
  5. use a times function to check both your GSM and Blynk connections, and re-establish them if they have been dropped

Unfortunately, I’m not familiar with your hardware, so I can’t help with code examp[le on how to do this.

You might also want to check that your board firmware is up to date, the library you’re using for the board is up to date and that you get the same issue if you use a different network provider.

Pete.

Can you provide a resource on what this means?