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?