메이커 Maker

Nano 33 IoT 스마트 팩토리 회로와 코드

지구빵집 2024. 6. 3. 07:23
반응형

 

인쇄 장비 동작 상태 정보를 수집하는 스마트 팩토리 과제로 수행하였다. 마이크로 컨틀롤러 보드는 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.

 

 

 

 

 

 

 

반응형