반응형

https://youtube.com/live/vxvtke2AAUc

[STM32#20] usart1에 esp01을 연결해서 wifi에 연결하고 mqtt프로토콜을 이용해서 데이터를 전송하는 방법 알아보기!(녹칸다 내맘대로 STM32)

심심한녹칸다의 내맘대로 STM32시리즈이다!

STM32시리즈의 모든 자료는 구글 슬라이드에 작성하고 모두에게 공유되어있음!
https://docs.google.com/presentation/d/1myA5iYbjuKsLWLqtRLKAiRfwUwvqB1d1RGjiMIIgp3I/edit?slide=id.g3a6f1f77138_2_233#slide=id.g3a6f1f77138_2_233

STM32에서 sscanf와 ring buffer를 활용해봅시당!

 

 


1.STM32에서 ESP01에 AT커맨드를 전송할때 제대로 전송되었는지를 확인할 수 있는 코드를 작성하시요!(테스트용코드)

/* USER CODE BEGIN 0 */
char cmd1[] = "AT\r\n";
char cmd2[] = "ATE0\r\n";
char mode_set[] = "AT+CWMODE=1\r\n";
char ap_con[] = "AT+CWJAP=\"popcorn\",\"11213144\"\r\n";
char ap_discon[] = "AT+CWQAP\r\n";
char tcp_con[] = "AT+CIPSTART=\"TCP\",\"broker.emqx.io\",1883\r\n";
char data;
#define b_size 256
uint8_t ring_buffer[b_size];
int head = 0;
int tail = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	ring_buffer[head++] = data;
	if(head == b_size) head = 0;
	HAL_UART_Receive_IT(&huart1, &data, 1); //인터럽트 재시작~
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
   //usart1에서 수신한 ring buffer안에 내용을 usart2에 출력한다!
	if(head != tail){
		char data = ring_buffer[tail];
		HAL_UART_Transmit(&huart2, &data, 1, 100);
		tail++;
		if (tail == b_size) tail = 0;
	}
}

/* USER CODE BEGIN 2 */
 HAL_UART_Receive_IT(&huart1, &data, 1); //수신인터럽트
 HAL_TIM_Base_Start_IT(&htim2); //타이머인터럽트
 char u2_data;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //usart2로 녹칸다가 문자 '1'을 전송하면 AT커맨드를 전송한다!
	  if(HAL_UART_Receive(&huart2, &u2_data, 1, 100) == HAL_OK){
		  if(u2_data == '1'){
			  //생존확인
			  HAL_UART_Transmit(&huart1, cmd1, strlen(cmd1), 100);
		  }else if(u2_data == '2'){
			  //echo off
			  HAL_UART_Transmit(&huart1, cmd2, strlen(cmd2), 100);
		  }else if(u2_data == '3'){
			  //스테이션 모드로 변경
			  HAL_UART_Transmit(&huart1, mode_set, strlen(mode_set), 100);
		  }else if(u2_data == '4'){
			  //인터넷공유기에 접쏙!
			  HAL_UART_Transmit(&huart1, ap_con, strlen(ap_con), 100);
		  }else if(u2_data == '5'){
			  //인터넷공유기 접속 해제!
			  HAL_UART_Transmit(&huart1, ap_discon, strlen(ap_discon), 100);
		  }else if(u2_data == '6'){
			  //브로커와 TCP 연결하기
			  //MQTT브로커와 TCP연결한다음, MQTT연결 명령어를 시간내 전송안하면
			  //서버가 자동으로 연결을 끊어버린다!
			  HAL_UART_Transmit(&huart1, tcp_con, strlen(tcp_con), 100);
		  }
	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


2.MQTT브로커랑 접속하고 녹칸다가 준비해놓은 기본 예제를 작동시켜보시오!

/* USER CODE BEGIN 0 */
char cmd1[] = "AT\r\n";
char cmd2[] = "ATE0\r\n";
char mode_set[] = "AT+CWMODE=1\r\n";
char ap_con[] = "AT+CWJAP=\"popcorn\",\"11213144\"\r\n";
char ap_discon[] = "AT+CWQAP\r\n";
char tcp_con[] = "AT+CIPSTART=\"TCP\",\"broker.emqx.io\",1883\r\n";
char data;
#define b_size 256
uint8_t ring_buffer[b_size];
int head = 0;
int tail = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	ring_buffer[head++] = data;
	if(head == b_size) head = 0;
	HAL_UART_Receive_IT(&huart1, &data, 1); //인터럽트 재시작~
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
   //usart1에서 수신한 ring buffer안에 내용을 usart2에 출력한다!
	if(head != tail){
		char data = ring_buffer[tail];
		HAL_UART_Transmit(&huart2, &data, 1, 100);
		tail++;
		if (tail == b_size) tail = 0;
	}
}
/* USER CODE END 0 */

/* USER CODE BEGIN 2 */
 HAL_UART_Receive_IT(&huart1, &data, 1); //수신인터럽트
 HAL_TIM_Base_Start_IT(&htim2); //타이머인터럽트
 char u2_data;
 uint8_t msg[256];
 //연결 해제
 HAL_UART_Transmit(&huart1,ap_discon,strlen(ap_discon),100);
 HAL_UART_Transmit(&huart2,"AP DIS CON\r\n",12,100);
 HAL_Delay(2000); //2초정도 기다리면 되겠지?
 //연결
 HAL_UART_Transmit(&huart1,ap_con,strlen(ap_con),100);
 HAL_UART_Transmit(&huart2,"AP CONNECTING\r\n",15,100);
 HAL_Delay(10000);
 //브로커 접속
 HAL_UART_Transmit(&huart1,tcp_con,strlen(tcp_con),100);
 HAL_UART_Transmit(&huart2,"BROKER CONNECTING\r\n",19,100);
 HAL_Delay(5000);
 //MQTT 연결
 uint8_t num1 = (HAL_GetTick()/1000) %10;
 uint8_t num2 = (HAL_GetTick()/100) %10;
 uint8_t num3 = (HAL_GetTick()/10) %10;
 uint8_t num4 = HAL_GetTick() %10;
 uint8_t MQTT_CONNECT[] = {0x10,0x14,0x00,0x04,'M','Q','T','T',0x04,0x02,0x00,0x3C,0x00,0x08,'N','O','C','K','0'+num1,'0'+num2,'0'+num3,'0'+num4};
 sprintf(msg, "AT+CIPSEND=%d\r\n", sizeof(MQTT_CONNECT));
 HAL_UART_Transmit(&huart1,msg,strlen(msg),100);
 HAL_Delay(1000);
 HAL_UART_Transmit(&huart1,MQTT_CONNECT,sizeof(MQTT_CONNECT),100);
 HAL_UART_Transmit(&huart2,"MQTT SET\r\n",10,100);
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  uint8_t MQTT_PUBLISH[] = {0x30,0x00,0x00,0x08,'N','O','C','K','A','N','D','A',0x00,0x00};
	  uint8_t MQTT_MSG[50];
	  sprintf(MQTT_MSG,"STM32 HAL_GetTick()=%d",HAL_GetTick());
	  MQTT_PUBLISH[13] = strlen(MQTT_MSG);
	  MQTT_PUBLISH[1] = (sizeof(MQTT_PUBLISH)-2) +strlen(MQTT_MSG);
	  sprintf(msg, "AT+CIPSEND=%d\r\n", sizeof(MQTT_PUBLISH)+strlen(MQTT_MSG));
	  HAL_UART_Transmit(&huart1,msg,strlen(msg),100);
	  HAL_Delay(500);
	  HAL_UART_Transmit(&huart1,MQTT_PUBLISH,sizeof(MQTT_PUBLISH),100);
	  HAL_UART_Transmit(&huart1,MQTT_MSG,strlen(MQTT_MSG),100);
	  HAL_UART_Transmit(&huart2,"publish\r\n",9,100);
	  HAL_Delay(500);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;

//전역으로 클래스선언
        MqttClient client;
        string clientId;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //메인폼이 로드되어서 사용자 눈에 딱 보였다!
            //MQTT 브로커와 연결하는 부분
            string BrokerAddress = "broker.emqx.io";
            client = new MqttClient(BrokerAddress);

            // register a callback-function (we have to implement, see below) which is called by the library when a message was received
            client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;

            // use a unique id as client id, each time we start the application
            clientId = Guid.NewGuid().ToString();
            client.Connect(clientId);

            richTextBox1.Text += "접속완료\n";


            //접속이 완료된 위치
            //Subscribe Topic 추가
            string[] mytopic = { "NOCKANDA" };
            byte[] qos = { 0 };
            client.Subscribe(mytopic, qos);

            richTextBox1.Text += "구독완료\n";
        }
        //MQTT이벤트 핸들러
        void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
        {
            string ReceivedMessage = Encoding.UTF8.GetString(e.Message, 2, e.Message.Length - 2);
            //DO SOMETHING..!

            richTextBox1.Text += "[수신] " + ReceivedMessage + "\n";

        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            //사용자가 프로그램을 껐다!
            //MQTT 연결 종료
            client.Disconnect();
        }


3.녹칸다의 STM32쉴드에 PA0에 붙어있는 가변저항값을 12bit로 측정해서 MQTT로 C#윈폼에 전송한다음 화면에 출력하시오! 

/* USER CODE BEGIN 0 */
char cmd1[] = "AT\r\n";
char cmd2[] = "ATE0\r\n";
char mode_set[] = "AT+CWMODE=1\r\n";
char ap_con[] = "AT+CWJAP=\"popcorn\",\"11213144\"\r\n";
char ap_discon[] = "AT+CWQAP\r\n";
char tcp_con[] = "AT+CIPSTART=\"TCP\",\"broker.emqx.io\",1883\r\n";
char data;
#define b_size 256
uint8_t ring_buffer[b_size];
int head = 0;
int tail = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	ring_buffer[head++] = data;
	if(head == b_size) head = 0;
	HAL_UART_Receive_IT(&huart1, &data, 1); //인터럽트 재시작~
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
   //usart1에서 수신한 ring buffer안에 내용을 usart2에 출력한다!
	if(head != tail){
		char data = ring_buffer[tail];
		HAL_UART_Transmit(&huart2, &data, 1, 100);
		tail++;
		if (tail == b_size) tail = 0;
	}
}
/* USER CODE END 0 */

/* USER CODE BEGIN 2 */
 HAL_UART_Receive_IT(&huart1, &data, 1); //수신인터럽트
 HAL_TIM_Base_Start_IT(&htim2); //타이머인터럽트
HAL_ADC_Start(&hadc1); //딱 한번만 호출
 uint16_t adc_value0 = 0;

 char u2_data;
 uint8_t msg[256];
 //연결 해제
 HAL_UART_Transmit(&huart1,ap_discon,strlen(ap_discon),100);
 HAL_UART_Transmit(&huart2,"AP DIS CON\r\n",12,100);
 HAL_Delay(2000); //2초정도 기다리면 되겠지?
 //연결
 HAL_UART_Transmit(&huart1,ap_con,strlen(ap_con),100);
 HAL_UART_Transmit(&huart2,"AP CONNECTING\r\n",15,100);
 HAL_Delay(10000);
 //브로커 접속
 HAL_UART_Transmit(&huart1,tcp_con,strlen(tcp_con),100);
 HAL_UART_Transmit(&huart2,"BROKER CONNECTING\r\n",19,100);
 HAL_Delay(5000);
 //MQTT 연결
 uint8_t num1 = (HAL_GetTick()/1000) %10;
 uint8_t num2 = (HAL_GetTick()/100) %10;
 uint8_t num3 = (HAL_GetTick()/10) %10;
 uint8_t num4 = HAL_GetTick() %10;
 uint8_t MQTT_CONNECT[] = {0x10,0x14,0x00,0x04,'M','Q','T','T',0x04,0x02,0x00,0x3C,0x00,0x08,'N','O','C','K','0'+num1,'0'+num2,'0'+num3,'0'+num4};
 sprintf(msg, "AT+CIPSEND=%d\r\n", sizeof(MQTT_CONNECT));
 HAL_UART_Transmit(&huart1,msg,strlen(msg),100);
 HAL_Delay(1000);
 HAL_UART_Transmit(&huart1,MQTT_CONNECT,sizeof(MQTT_CONNECT),100);
 HAL_UART_Transmit(&huart2,"MQTT SET\r\n",10,100);
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
	  {
		  adc_value0 = HAL_ADC_GetValue(&hadc1);
	  }
	  uint8_t MQTT_PUBLISH[] = {0x30,0x00,0x00,0x08,'N','O','C','K','A','N','D','A',0x00,0x00};
	  uint8_t MQTT_MSG[50];
	  sprintf(MQTT_MSG,"%d,%d",msg_num,adc_value0);
	  msg_num++;
	  MQTT_PUBLISH[13] = strlen(MQTT_MSG);
	  MQTT_PUBLISH[1] = (sizeof(MQTT_PUBLISH)-2) +strlen(MQTT_MSG);
	  sprintf(msg, "AT+CIPSEND=%d\r\n", sizeof(MQTT_PUBLISH)+strlen(MQTT_MSG));
	  HAL_UART_Transmit(&huart1,msg,strlen(msg),100);
	  HAL_Delay(500);
	  HAL_UART_Transmit(&huart1,MQTT_PUBLISH,sizeof(MQTT_PUBLISH),100);
	  HAL_UART_Transmit(&huart1,MQTT_MSG,strlen(MQTT_MSG),100);
	  HAL_UART_Transmit(&huart2,"publish\r\n",9,100);
	  HAL_Delay(500);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;

//전역으로 클래스선언
        MqttClient client;
        string clientId;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //메인폼이 로드되어서 사용자 눈에 딱 보였다!
            //MQTT 브로커와 연결하는 부분
            string BrokerAddress = "broker.emqx.io";
            client = new MqttClient(BrokerAddress);

            // register a callback-function (we have to implement, see below) which is called by the library when a message was received
            client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;

            // use a unique id as client id, each time we start the application
            clientId = Guid.NewGuid().ToString();
            client.Connect(clientId);

            richTextBox1.Text += "접속완료\n";


            //접속이 완료된 위치
            //Subscribe Topic 추가
            string[] mytopic = { "NOCKANDA" };
            byte[] qos = { 0 };
            client.Subscribe(mytopic, qos);

            richTextBox1.Text += "구독완료\n";
        }
        //MQTT이벤트 핸들러
        void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
        {
            string ReceivedMessage = Encoding.UTF8.GetString(e.Message, 2, e.Message.Length - 2);
            //DO SOMETHING..!

            richTextBox1.Text += "[수신] " + ReceivedMessage + "\n";

            string[] data = ReceivedMessage.Split(',');
            if(data.Length == 2)
            {
                textBox1.Text = data[0];
                textBox2.Text = data[1];
            }
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            //사용자가 프로그램을 껐다!
            //MQTT 연결 종료
            client.Disconnect();
        }


4.STM32쉴드에 붙어있는 온습도센서인 DHT-11의 값을 측정해서 MQTT로 C#윈폼에 전송한다음 화면에 출력하시오! 

/* USER CODE BEGIN 0 */
char cmd1[] = "AT\r\n";
char cmd2[] = "ATE0\r\n";
char mode_set[] = "AT+CWMODE=1\r\n";
char ap_con[] = "AT+CWJAP=\"popcorn\",\"11213144\"\r\n";
char ap_discon[] = "AT+CWQAP\r\n";
char tcp_con[] = "AT+CIPSTART=\"TCP\",\"broker.emqx.io\",1883\r\n";
char data;
#define b_size 256
uint8_t ring_buffer[b_size];
int head = 0;
int tail = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	ring_buffer[head++] = data;
	if(head == b_size) head = 0;
	HAL_UART_Receive_IT(&huart1, &data, 1); //인터럽트 재시작~
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
   //usart1에서 수신한 ring buffer안에 내용을 usart2에 출력한다!
	if(head != tail){
		char data = ring_buffer[tail];
		HAL_UART_Transmit(&huart2, &data, 1, 100);
		tail++;
		if (tail == b_size) tail = 0;
	}
}

#define delay_ms HAL_Delay
#define SYS_CLOCK    64
#define SYSTICK_LOAD 63999
uint32_t millis_cnt = 0;
uint32_t millis() {
return millis_cnt;
}
uint32_t micros() {
return (millis_cnt & 0x3FFFFF) * 1000 + (SYSTICK_LOAD - SysTick->VAL) / SYS_CLOCK;
}
void delay_us(uint32_t us) {  // 64MHz 보정
if (us > 1) {
 uint32_t count = us * 7 - 6;
 while (count--);
} else {
 uint32_t count = 2;
 while (count--);
}
}
union {
uint32_t data;
struct {
  uint8_t temp_d;
  uint8_t temp_i;
  uint8_t rh_d;
  uint8_t rh_i;
};
} DHT;

uint8_t DHT_read () {
uint8_t i, check_sum;
uint32_t start;
check_sum = 0;
DHT.data = 0;
GPIOC->CRL = (GPIOC->CRL&0xFFFFFF0F)|(7<<(1*4));  // Output Open-drain (Master send LOW signal)
delay_ms(18);
GPIOC->CRL= (GPIOC->CRL&0xFFFFFF0F)|(4<<(1*4));  // Floating input (Master send HIGH signal & data receive)
start = micros();
while (GPIOC->IDR&(1<<1)) {
  if (micros()-start > 50) return 1;  // 20~40us
}
start = micros();
while (!(GPIOC->IDR&(1<<1))) {
  if (micros()-start > 120) return 2;  // 80us
}
start = micros();
while (GPIOC->IDR&(1<<1)) {
  if (micros()-start > 120) return 3;  // 80us
}
for (i = 0; i < 32; i++) {
  while (!(GPIOC->IDR&(1<<1))); // 50us
  start = micros();
  while (GPIOC->IDR&(1<<1));
  if (micros()-start > 50) DHT.data |= (0x80000000 >> i); // "0"=26~28us, "1"=70us
}
for (i = 0; i < 8; i++) {
  while (!(GPIOC->IDR&(1<<1))); // 50us
  start = micros();
  while (GPIOC->IDR&(1<<1));
  if (micros()-start > 50) check_sum |= (0x80 >> i);
}
if ((DHT.rh_i + DHT.rh_d + DHT.temp_i + DHT.temp_d) == check_sum) return 0;
else return 4;
}
/* USER CODE END 0 */

/* USER CODE BEGIN 2 */
 HAL_UART_Receive_IT(&huart1, &data, 1); //수신인터럽트
 HAL_TIM_Base_Start_IT(&htim2); //타이머인터럽트
 HAL_ADC_Start(&hadc1); //딱 한번만 호출
 uint16_t adc_value0 = 0;
 char u2_data;
 uint8_t msg[256];
 //연결 해제
 HAL_UART_Transmit(&huart1,ap_discon,strlen(ap_discon),100);
 HAL_UART_Transmit(&huart2,"AP DIS CON\r\n",12,100);
 HAL_Delay(2000); //2초정도 기다리면 되겠지?
 //연결
 HAL_UART_Transmit(&huart1,ap_con,strlen(ap_con),100);
 HAL_UART_Transmit(&huart2,"AP CONNECTING\r\n",15,100);
 HAL_Delay(10000);
 //브로커 접속
 HAL_UART_Transmit(&huart1,tcp_con,strlen(tcp_con),100);
 HAL_UART_Transmit(&huart2,"BROKER CONNECTING\r\n",19,100);
 HAL_Delay(5000);

 //MQTT 연결
 uint8_t num1 = (HAL_GetTick()/1000) %10;
 uint8_t num2 = (HAL_GetTick()/100) %10;
 uint8_t num3 = (HAL_GetTick()/10) %10;
 uint8_t num4 = HAL_GetTick() %10;
 uint8_t MQTT_CONNECT[] = {0x10,0x14,0x00,0x04,'M','Q','T','T',0x04,0x02,0x00,0x3C,0x00,0x08,'N','O','C','K','0'+num1,'0'+num2,'0'+num3,'0'+num4};
 sprintf(msg, "AT+CIPSEND=%d\r\n", sizeof(MQTT_CONNECT));
 HAL_UART_Transmit(&huart1,msg,strlen(msg),100);
 HAL_Delay(1000);
 HAL_UART_Transmit(&huart1,MQTT_CONNECT,sizeof(MQTT_CONNECT),100);
 HAL_UART_Transmit(&huart2,"MQTT SET\r\n",10,100);
 int msg_num = 0;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  uint8_t error_no = DHT_read();
	  if(error_no == 0){  // 정상일 때 처리
		  float temp = 0;
		  float humi = 0;
		  temp = DHT.temp_i;
		  if (DHT.temp_d & 0x80) {
			  temp = -1 - temp;
		  }
		  temp += (DHT.temp_d & 0x0f) * 0.1;
		  humi = DHT.rh_i + DHT.rh_d * 0.1;

		  uint8_t MQTT_PUBLISH[] = {0x30,0x00,0x00,0x08,'N','O','C','K','A','N','D','A',0x00,0x00};
		  uint8_t MQTT_MSG[50];
		  sprintf(MQTT_MSG,"%d,%.2f,%.2f",msg_num,temp,humi);
		  msg_num++;
		  MQTT_PUBLISH[13] = strlen(MQTT_MSG);
		  MQTT_PUBLISH[1] = (sizeof(MQTT_PUBLISH)-2) +strlen(MQTT_MSG);
		  sprintf(msg, "AT+CIPSEND=%d\r\n", sizeof(MQTT_PUBLISH)+strlen(MQTT_MSG));
		  HAL_UART_Transmit(&huart1,msg,strlen(msg),100);
		  HAL_Delay(500);
		  HAL_UART_Transmit(&huart1,MQTT_PUBLISH,sizeof(MQTT_PUBLISH),100);
		  HAL_UART_Transmit(&huart1,MQTT_MSG,strlen(MQTT_MSG),100);
		  HAL_UART_Transmit(&huart2,"publish\r\n",9,100);
	  } else {
		  //측정실패
	  }
	  HAL_Delay(1500);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;

//전역으로 클래스선언
        MqttClient client;
        string clientId;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //메인폼이 로드되어서 사용자 눈에 딱 보였다!
            //MQTT 브로커와 연결하는 부분
            string BrokerAddress = "broker.emqx.io";
            client = new MqttClient(BrokerAddress);

            // register a callback-function (we have to implement, see below) which is called by the library when a message was received
            client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;

            // use a unique id as client id, each time we start the application
            clientId = Guid.NewGuid().ToString();
            client.Connect(clientId);

            richTextBox1.Text += "접속완료\n";


            //접속이 완료된 위치
            //Subscribe Topic 추가
            string[] mytopic = { "NOCKANDA" };
            byte[] qos = { 0 };
            client.Subscribe(mytopic, qos);

            richTextBox1.Text += "구독완료\n";
        }
        //MQTT이벤트 핸들러
        void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
        {
            string ReceivedMessage = Encoding.UTF8.GetString(e.Message, 2, e.Message.Length - 2);
            //DO SOMETHING..!

            richTextBox1.Text += "[수신] " + ReceivedMessage + "\n";
            string[] data = ReceivedMessage.Split(',');
            if(data.Length == 3)
            {
                textBox1.Text = data[0];
                textBox2.Text = data[1];
                textBox3.Text = data[2];
            }

        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            //사용자가 프로그램을 껐다!
            //MQTT 연결 종료
            client.Disconnect();
        }


5.예제4에서 수신받은 온도와 습도값을 좀더 그럴싸하게 보이도록 하고 마무리하시오!

/* USER CODE BEGIN 0 */
char cmd1[] = "AT\r\n";
char cmd2[] = "ATE0\r\n";
char mode_set[] = "AT+CWMODE=1\r\n";
char ap_con[] = "AT+CWJAP=\"popcorn\",\"11213144\"\r\n";
char ap_discon[] = "AT+CWQAP\r\n";
char tcp_con[] = "AT+CIPSTART=\"TCP\",\"broker.emqx.io\",1883\r\n";
char data;
#define b_size 256
uint8_t ring_buffer[b_size];
int head = 0;
int tail = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	ring_buffer[head++] = data;
	if(head == b_size) head = 0;
	HAL_UART_Receive_IT(&huart1, &data, 1); //인터럽트 재시작~
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
   //usart1에서 수신한 ring buffer안에 내용을 usart2에 출력한다!
	if(head != tail){
		char data = ring_buffer[tail];
		HAL_UART_Transmit(&huart2, &data, 1, 100);
		tail++;
		if (tail == b_size) tail = 0;
	}
}

#define delay_ms HAL_Delay
#define SYS_CLOCK    64
#define SYSTICK_LOAD 63999
uint32_t millis_cnt = 0;
uint32_t millis() {
return millis_cnt;
}
uint32_t micros() {
return (millis_cnt & 0x3FFFFF) * 1000 + (SYSTICK_LOAD - SysTick->VAL) / SYS_CLOCK;
}
void delay_us(uint32_t us) {  // 64MHz 보정
if (us > 1) {
 uint32_t count = us * 7 - 6;
 while (count--);
} else {
 uint32_t count = 2;
 while (count--);
}
}
union {
uint32_t data;
struct {
  uint8_t temp_d;
  uint8_t temp_i;
  uint8_t rh_d;
  uint8_t rh_i;
};
} DHT;

uint8_t DHT_read () {
uint8_t i, check_sum;
uint32_t start;
check_sum = 0;
DHT.data = 0;
GPIOC->CRL = (GPIOC->CRL&0xFFFFFF0F)|(7<<(1*4));  // Output Open-drain (Master send LOW signal)
delay_ms(18);
GPIOC->CRL= (GPIOC->CRL&0xFFFFFF0F)|(4<<(1*4));  // Floating input (Master send HIGH signal & data receive)
start = micros();
while (GPIOC->IDR&(1<<1)) {
  if (micros()-start > 50) return 1;  // 20~40us
}
start = micros();
while (!(GPIOC->IDR&(1<<1))) {
  if (micros()-start > 120) return 2;  // 80us
}
start = micros();
while (GPIOC->IDR&(1<<1)) {
  if (micros()-start > 120) return 3;  // 80us
}
for (i = 0; i < 32; i++) {
  while (!(GPIOC->IDR&(1<<1))); // 50us
  start = micros();
  while (GPIOC->IDR&(1<<1));
  if (micros()-start > 50) DHT.data |= (0x80000000 >> i); // "0"=26~28us, "1"=70us
}
for (i = 0; i < 8; i++) {
  while (!(GPIOC->IDR&(1<<1))); // 50us
  start = micros();
  while (GPIOC->IDR&(1<<1));
  if (micros()-start > 50) check_sum |= (0x80 >> i);
}
if ((DHT.rh_i + DHT.rh_d + DHT.temp_i + DHT.temp_d) == check_sum) return 0;
else return 4;
}
/* USER CODE END 0 */

/* USER CODE BEGIN 2 */
 HAL_UART_Receive_IT(&huart1, &data, 1); //수신인터럽트
 HAL_TIM_Base_Start_IT(&htim2); //타이머인터럽트
 HAL_ADC_Start(&hadc1); //딱 한번만 호출
 uint16_t adc_value0 = 0;
 char u2_data;
 uint8_t msg[256];
 //연결 해제
 HAL_UART_Transmit(&huart1,ap_discon,strlen(ap_discon),100);
 HAL_UART_Transmit(&huart2,"AP DIS CON\r\n",12,100);
 HAL_Delay(2000); //2초정도 기다리면 되겠지?
 //연결
 HAL_UART_Transmit(&huart1,ap_con,strlen(ap_con),100);
 HAL_UART_Transmit(&huart2,"AP CONNECTING\r\n",15,100);
 HAL_Delay(10000);
 //브로커 접속
 HAL_UART_Transmit(&huart1,tcp_con,strlen(tcp_con),100);
 HAL_UART_Transmit(&huart2,"BROKER CONNECTING\r\n",19,100);
 HAL_Delay(5000);

 //MQTT 연결
 uint8_t num1 = (HAL_GetTick()/1000) %10;
 uint8_t num2 = (HAL_GetTick()/100) %10;
 uint8_t num3 = (HAL_GetTick()/10) %10;
 uint8_t num4 = HAL_GetTick() %10;
 uint8_t MQTT_CONNECT[] = {0x10,0x14,0x00,0x04,'M','Q','T','T',0x04,0x02,0x00,0x3C,0x00,0x08,'N','O','C','K','0'+num1,'0'+num2,'0'+num3,'0'+num4};
 sprintf(msg, "AT+CIPSEND=%d\r\n", sizeof(MQTT_CONNECT));
 HAL_UART_Transmit(&huart1,msg,strlen(msg),100);
 HAL_Delay(1000);
 HAL_UART_Transmit(&huart1,MQTT_CONNECT,sizeof(MQTT_CONNECT),100);
 HAL_UART_Transmit(&huart2,"MQTT SET\r\n",10,100);
 int msg_num = 0;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  uint8_t error_no = DHT_read();
	  if(error_no == 0){  // 정상일 때 처리
		  float temp = 0;
		  float humi = 0;
		  temp = DHT.temp_i;
		  if (DHT.temp_d & 0x80) {
			  temp = -1 - temp;
		  }
		  temp += (DHT.temp_d & 0x0f) * 0.1;
		  humi = DHT.rh_i + DHT.rh_d * 0.1;

		  uint8_t MQTT_PUBLISH[] = {0x30,0x00,0x00,0x08,'N','O','C','K','A','N','D','A',0x00,0x00};
		  uint8_t MQTT_MSG[50];
		  sprintf(MQTT_MSG,"%d,%.2f,%.2f",msg_num,temp,humi);
		  msg_num++;
		  MQTT_PUBLISH[13] = strlen(MQTT_MSG);
		  MQTT_PUBLISH[1] = (sizeof(MQTT_PUBLISH)-2) +strlen(MQTT_MSG);
		  sprintf(msg, "AT+CIPSEND=%d\r\n", sizeof(MQTT_PUBLISH)+strlen(MQTT_MSG));
		  HAL_UART_Transmit(&huart1,msg,strlen(msg),100);
		  HAL_Delay(500);
		  HAL_UART_Transmit(&huart1,MQTT_PUBLISH,sizeof(MQTT_PUBLISH),100);
		  HAL_UART_Transmit(&huart1,MQTT_MSG,strlen(MQTT_MSG),100);
		  HAL_UART_Transmit(&huart2,"publish\r\n",9,100);
	  } else {
		  //측정실패
	  }
	  HAL_Delay(1500);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;

//전역으로 클래스선언
        MqttClient client;
        string clientId;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //메인폼이 로드되어서 사용자 눈에 딱 보였다!
            //MQTT 브로커와 연결하는 부분
            string BrokerAddress = "broker.emqx.io";
            client = new MqttClient(BrokerAddress);

            // register a callback-function (we have to implement, see below) which is called by the library when a message was received
            client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;

            // use a unique id as client id, each time we start the application
            clientId = Guid.NewGuid().ToString();
            client.Connect(clientId);

            richTextBox1.Text += "접속완료\n";


            //접속이 완료된 위치
            //Subscribe Topic 추가
            string[] mytopic = { "NOCKANDA" };
            byte[] qos = { 0 };
            client.Subscribe(mytopic, qos);

            richTextBox1.Text += "구독완료\n";
        }
        //MQTT이벤트 핸들러
        void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
        {
            string ReceivedMessage = Encoding.UTF8.GetString(e.Message, 2, e.Message.Length - 2);
            //DO SOMETHING..!

            string[] data = ReceivedMessage.Split(',');
            if(data.Length == 3)
            {
                textBox1.Text = data[0];
                textBox2.Text = data[1]; //온도
                textBox3.Text = data[2]; //습도
                float temp = float.Parse(data[1]);
                float humi = float.Parse(data[2]);
                aGauge1.Value = temp;
                aGauge2.Value = humi;
            }
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            //사용자가 프로그램을 껐다!
            //MQTT 연결 종료
            client.Disconnect();
        }
반응형
Posted by 덕력킹
,