인쇄 장비 동작 상태 정보를 수집하는 스마트 팩토리 과제로 수행하였다. 마이크로 컨틀롤러 보드는 Nano 33 IoT 보드를 사용했고 온도 습도센서와 초음파 센서, 출력장치로 OLED를 달았다.
서버 프로그램은 납품 회사에서 담당했다. 통신쪽 프로그램은 여전히 어려운데 좀 더 파야겠다.

코드
/*
* base Arduino Nano 33 IoTArduino and SSD1306 OLED display.
* This is a free software with NO WARRANTY.
* https://www.wepnp.com/
* https://simple-circuit.com/
*/
#include <Wire.h> // include Arduino wire library (required for I2C devices)
#include <Adafruit_GFX.h> // include Adafruit graphics library
#include <Adafruit_SSD1306.h> // include Adafruit SSD1306 OLED display driver
#include <SimpleDHT.h>
#include "arduino_secrets.h"
#include <SPI.h>
#include <WiFiNINA.h>
#define OLED_RESET 4 // define display reset pin
Adafruit_SSD1306 display(OLED_RESET);
//define DHT11 pin connection
int pinDHT11 = 9;
SimpleDHT11 dht11;
#define trigPin 6 // trigPin을 6으로 설정합니다.
#define echoPin 7 // echoPin을 7로 설정합니다.
uint32_t sampleRate = 1000; //sample rate in milliseconds, determines how often TC5_Handler is called
uint32_t onesecondinterval=0;
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
char server[]="jarvis.wepnp.com";
//== IPAddress servernaeme(117,16,231,212);
WiFiClient client;
const char* host = "jarvis.wepnp.com"; // --> "openapi.airkorea.or.kr"
const uint16_t port = 80; // --> 80
//SETTING VALUE
const uint32_t sendingPerod = 60; //second
const String EQUIP_NAME = "pr-01";
const int operation_distance = 13; //operation less then 13
boolean running = false;
void setup(void)
{
initial_oled();
//Scheduler.startLoop(temphumi_display);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(trigPin, OUTPUT); // trigPin 핀을 출력핀으로 설정합니다.
pinMode(echoPin, INPUT); // echoPin 핀을 입력핀으로 설정합니다.
//setup Timer
tcConfigure(sampleRate); //configure the timer to run at <sampleRate>Hertz
tcStartCounter(); //starts the timer
Serial.begin(9600);
/*while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}*/
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
// delay(10000);
Serial.print(".");
}
Serial.println("Connected to wifi");
printWifiStatus();
//only 1 time execute in setup function
to_oled_temphumidata();
send_equipment_sensordata();
}
String url = "https://jarvis.wepnp.com/API/v2/kpi/data/insert";
String key = "YmVsbGFuZWxsYTplU21aNmJvMjFjVGt1dnA3bXM2ZFI0Snlabw==";
uint32_t time_counter_30sec = 0; //second infinit counter
uint32_t ultrasonic_count = 0; //second infinit counter
uint32_t every_5sec_counter = 0; //every 5second
void loop()
{
//delay(1000);
if(every_5sec_counter > 5)
{
to_oled_temphumidata();
every_5sec_counter = 0;
}
if(onesecondinterval >= sendingPerod) //data Sending Interval
{
send_equipment_sensordata();
onesecondinterval = 0;
}
ultrasonic_sensor();
if(time_counter_30sec > 30)
{
Serial.println(ultrasonic_count);
if(ultrasonic_count > 0)
{
running = true;
ultrasonic_count = 0;
}
else
running = false;
time_counter_30sec = 0;
//Serial.println(running);
}
}
void ultrasonic_sensor()
{
long duration, distance; // 각 변수를 선언합니다.
digitalWrite(trigPin, LOW); // trigPin에 LOW를 출력하고
delayMicroseconds(2); // 2 마이크로초가 지나면
digitalWrite(trigPin, HIGH); // trigPin에 HIGH를 출력합니다.
delayMicroseconds(10); // trigPin을 10마이크로초 동안 기다렸다가
digitalWrite(trigPin, LOW); // trigPin에 LOW를 출력합니다.
duration = pulseIn(echoPin, HIGH); // echoPin핀에서 펄스값을 받아옵니다.
distance = duration * 17 / 1000; // duration을 연산하여 센싱한 거리값을 distance에 저장합니다.
if(distance < operation_distance) //near distance
ultrasonic_count++;
//Serial.println(ultrasonic_count);
}
void send_equipment_sensordata()
{
Serial.print("connecting to ");
Serial.print(host);
Serial.print(':');
Serial.println(port);
//Use WiFiClient class to create TCP connections
WiFiClient client;
if (!client.connect(host, port))
{
Serial.println("connection failed");
delay(5000);
return;
}
else
{
Serial.println("connect server!");
}
digitalWrite(LED_BUILTIN, HIGH);
if(client.connected()) //Check WiFi connection status
{
//POST data Set
client.print("GET /API/v2/kpi/data/insert?data={%22machine%22:%22");
client.print(EQUIP_NAME);
client.print("%22,%22temperature%22:");
client.print(get_temp());
client.print(",%22humidity%22:");
client.print(get_humi());
client.print(",%22power%22:");
client.print(get_operation_state());
client.print(",%22count%22:");
client.print(get_operation_count());
client.println("} HTTP/1.1");
client.println("Host: jarvis.wepnp.com");
client.println("Authorization: Basic YmVsbGFuZWxsYTplU21aNmJvMjFjVGt1dnA3bXM2ZFI0Snlabw==");
client.println();
// wait for data to be available
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
//delay(60000);
return;
}
}
// Read all the lines of the reply from server and print them to Serial
Serial.println("receiving from remote server");
// not testing 'client.connected()' since we do not need to send data here
while (client.available()) {
char ch = static_cast<char>(client.read());
Serial.print(ch);
}
// Close the connection
Serial.println();
Serial.println("closing connection");
client.stop();
Serial.println("Complete");
}
digitalWrite(LED_BUILTIN, LOW);
//delay(60000); //->timer interrupt insert, not need 20201026
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
void initial_oled()
{
//initialize the SSD1306 OLED display with I2C address = 0x3D
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
// clear the display buffer.
display.clearDisplay();
display.setTextSize(1); // text size = 1
display.setTextColor(WHITE, BLACK); // set text color to white and black background
display.setCursor(15, 0); // move cursor to position (15, 0) pixel
display.print("Device Status");
display.display(); // update the display
display.setTextSize(2); // text size = 2
}
char _buffer[8];
int get_temp()
{
delay(2000);
byte temperature = 0;
byte humidity = 0;
if (dht11.read(pinDHT11, &temperature, &humidity, NULL)) {
Serial.print("Read DHT11 temp failed.");
return 0;
}
else{
return (int)temperature;
}
}
int get_humi()
{
delay(2000);
byte temperature = 0;
byte humidity = 0;
if (dht11.read(pinDHT11, &temperature, &humidity, NULL)) {
Serial.print("Read DHT11 humi failed.");
return 0;
}else{
return (int)humidity;
}
}
boolean get_operation_state()
{
//ultra sonic test
return running;
}
int operation_count=0;
int get_operation_count()
{
operation_count++;
return operation_count;
}
void to_oled_temphumidata()
{
byte temperature = 0;
byte humidity = 0;
if (dht11.read(pinDHT11, &temperature, &humidity, NULL)) {
Serial.print("Read DHT11 failed.");
return;
}
display.setCursor(23, 10);
sprintf(_buffer, "%d C", (int)temperature);
display.print(_buffer);
display.setCursor(23, 30);
sprintf(_buffer, "%d ", (int)humidity);
display.print(_buffer);
display.setCursor(60, 30);
sprintf(_buffer, "/", (int)humidity);
display.print(_buffer);
display.setCursor(23, 50);
if(running)
{sprintf(_buffer, "%s", "Eq On ");}
else
{sprintf(_buffer, "%s", "Eq Off");}
display.print(_buffer);
display.drawCircle(54, 12, 2, WHITE);
display.drawCircle(60, 32, 2, WHITE);
display.drawCircle(70, 42, 2, WHITE);
// update the display
display.display();
// DHT11 sampling rate is 1HZ.
delay(2000);
}
void to_oled_temphumidata_test()
{
byte temperature = 0;
byte humidity = 0;
if (dht11.read(pinDHT11, &temperature, &humidity, NULL)) {
Serial.print("Read DHT11 failed.");
return;
}
Serial.print("Sample OK: ");
Serial.print((int)temperature); Serial.print(" *C, ");
Serial.print((int)humidity); Serial.println(" %");
// DHT11 sampling rate is 1HZ.
delay(2000);
}
//Here Start Timer function
//this function gets called by the interrupt at <sampleRate>Hertz
void TC5_Handler (void) {
//YOUR CODE HERE
onesecondinterval++;
time_counter_30sec++;
every_5sec_counter++;
//Serial.println(onesecondinterval);
/*if(state == true) {
digitalWrite(LED_PIN,HIGH);
} else {
digitalWrite(LED_PIN,LOW);
}
state = !state;*/
// END OF YOUR CODE
TC5->COUNT16.INTFLAG.bit.MC0 = 1; //Writing a 1 to INTFLAG.bit.MC0 clears the interrupt so that it will run again
}
/*
* TIMER SPECIFIC FUNCTIONS FOLLOW
* you shouldn't change these unless you know what you're doing
*/
//Configures the TC to generate output events at the sample frequency.
//Configures the TC in Frequency Generation mode, with an event output once
//each time the audio sample frequency period expires.
void tcConfigure(int sampleRate)
{
// select the generic clock generator used as source to the generic clock multiplexer
GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TC4_TC5)) ;
while (GCLK->STATUS.bit.SYNCBUSY);
tcReset(); //reset TC5
// Set Timer counter 5 Mode to 16 bits, it will become a 16bit counter ('mode1' in the datasheet)
TC5->COUNT16.CTRLA.reg |= TC_CTRLA_MODE_COUNT16;
// Set TC5 waveform generation mode to 'match frequency'
TC5->COUNT16.CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ;
//set prescaler
//the clock normally counts at the GCLK_TC frequency, but we can set it to divide that frequency to slow it down
//you can use different prescaler divisons here like TC_CTRLA_PRESCALER_DIV1 to get a different range
TC5->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCALER_DIV1024 | TC_CTRLA_ENABLE; //it will divide GCLK_TC frequency by 1024
//set the compare-capture register.
//The counter will count up to this value (it's a 16bit counter so we use uint16_t)
//this is how we fine-tune the frequency, make it count to a lower or higher value
//system clock should be 1MHz (8MHz/8) at Reset by default
TC5->COUNT16.CC[0].reg = (uint16_t) (SystemCoreClock / sampleRate);
while (tcIsSyncing());
// Configure interrupt request
NVIC_DisableIRQ(TC5_IRQn);
NVIC_ClearPendingIRQ(TC5_IRQn);
NVIC_SetPriority(TC5_IRQn, 0);
NVIC_EnableIRQ(TC5_IRQn);
// Enable the TC5 interrupt request
TC5->COUNT16.INTENSET.bit.MC0 = 1;
while (tcIsSyncing()); //wait until TC5 is done syncing
}
//Function that is used to check if TC5 is done syncing
//returns true when it is done syncing
bool tcIsSyncing()
{
return TC5->COUNT16.STATUS.reg & TC_STATUS_SYNCBUSY;
}
//This function enables TC5 and waits for it to be ready
void tcStartCounter()
{
TC5->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE; //set the CTRLA register
while (tcIsSyncing()); //wait until snyc'd
}
//Reset TC5
void tcReset()
{
TC5->COUNT16.CTRLA.reg = TC_CTRLA_SWRST;
while (tcIsSyncing());
while (TC5->COUNT16.CTRLA.bit.SWRST);
}
//disable TC5
void tcDisable()
{
TC5->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE;
while (tcIsSyncing());
}
// end of code.
'메이커 Maker' 카테고리의 다른 글
| LACE로 생활의 소리를 최대한 활용하기 (1) | 2024.08.06 |
|---|---|
| PM2008 레이저 입자 센서 (1) | 2024.07.30 |
| 센서 모듈 회로도 모음 (0) | 2024.06.24 |
| 전기 전자회로 기호표 Circuit Symbols (0) | 2024.06.04 |
| 아두이노 나노 미세먼지 모니터 보드 설계 (0) | 2024.06.03 |
| Nano 33 IoT 스마트 팩토리 보드 (1) | 2024.05.30 |
| LED 직렬 저항 계산 방법 (0) | 2024.05.30 |
| Level Shifter 회로 BSS138 사용 (0) | 2024.05.24 |
취업, 창업의 막막함, 외주 관리, 제품 부재!
당신의 고민은 무엇입니까? 현실과 동떨어진 교육, 실패만 반복하는 외주 계약,
아이디어는 있지만 구현할 기술이 없는 막막함.
우리는 알고 있습니다. 문제의 원인은 '명확한 학습, 실전 경험과 신뢰할 수 있는 기술력의 부재'에서 시작됩니다.
이제 고민을 멈추고, 캐어랩을 만나세요!
코딩(펌웨어), 전자부품과 디지털 회로설계, PCB 설계 제작, 고객(시장/수출) 발굴과 마케팅 전략으로 당신을 지원합니다.
제품 설계의 고수는 성공이 만든 게 아니라 실패가 만듭니다. 아이디어를 양산 가능한 제품으로!
귀사의 제품을 만드세요. 교육과 개발 실적으로 신뢰할 수 있는 파트너를 확보하세요.
지난 30년 여정, 캐어랩이 얻은 모든 것을 함께 나누고 싶습니다.
귀사가 성공하기까지의 긴 고난의 시간을 캐어랩과 함께 하세요.
캐어랩