프로젝트 개요
개발동기
코로나 및 사회적 격리 장기화 또는 코로나 사태 이후 경제적으로 어려워지거나 사람들을 만나기 힘들어지면서 우울감·외로움과 고독을 느끼는 사람들이 늘어나고 있는 추세 인터넷의 취약계층 들은 인터넷 정보의 접근성도 취약하다. 경로당에서 친구들하고 만나는 게 전부였을 만큼 스트레스를 풀 수 있는 자원 자체가 빈약하다. 불안감은 높은데 고립되는 것이 쉬움
➜ 우울감 , 외로움 등을 느끼는 사람들이 많이 생긴 것을 인지 , 이를 해결해줄 제품이 필요하다고 느낌.프로젝트 작품 원리 설명
조명 : RGB LED를 사용하지만 브라질의 기술자인 알프레도 모제가 개발한 페트병과 물, 표백제만으로 전구의 밝기와 맞먹는 페트병 전구에 LED를 4방향으로 설치하여 작은 전력으로 더 밝은 빛을 낼수 있도록 함.
-> 환경오염으로 문제가 심각한 현대에 작은 전력으로 충분한 빛을 제공해줄수 있음.
라즈베리파이
카메라 모듈과 연결하여 사용자가 web에서 접속하여 식물의 상태를 확인하고 정기적으로 기록할수 있도록 해준다.
stm32와 UART 통신을 사용하여 웹에서 RGB LED의 색을 바꿀수 있도록 해준다.
웹을 통해서 선인장이 심어지고나서 30일 주기로 물을 줄수 있도록 알림서비스를 제공한다. -> 식물을 연구하거나 기록하는 사람일 경우에는 카메라 모듈로 기록을 해주는것이 편하게 느껴짐.
STM32F103RB 보드를 사용합니다.
1. RGB LED 제어하기
사용하는 모듈은 ws2812B RGB LED 이다.
1-1 clock 설정하기
TIM의 DMA를 사용하여 RGB LED를 사용할 예정임으로 CLOCK 을 맞춰야됨
ws2812B 모듈의 data sheet 에 따르면 1 bit에 high 와 low비가 얼마정도여야 high로 인식하는지가 나와 있다.STM32F103RB 보드의 최대 클럭은 72MHz임으로
Counter Period
값을 90을 줌으로써 1비트에 1250ns를 맞출 수 있다. (72MH 1250n = 90)위와 같은 공식을 활용하여 HIGH 와 LOW 는 50 과 25로 구할 수 있다.
(LOW => 72MH 0.35us = 25.20 | HIGH => 72MH * 0.7us = 50.40 소수점은 버림)
이렇게 설정한 클럭은 TIM에 할당함( TIM로 DMA사용해서 제어할 꺼임 )DMA설정
#include "main.h"
#include <stdlib.h>
#include <string.h>
TIM_HandleTypeDef htim3;
DMA_HandleTypeDef hdma_tim3_ch1_trig;
#define LED 12 // 사용하는 RGB LED 키는 모듈의 LED 개수를 뜻함
#define Lo 25 // LED LOW
#define Hi 50 // LED HIGH
uint8_t buf[LED*24+48]={
Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,// Green 0
Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,// Red 1
Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,// Blue 2
Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi,// White 3
Lo,Lo,Lo,Lo,Lo,Hi,Lo,Lo,Hi,Hi,Hi,Lo,Hi,Hi,Hi,Hi,Lo,Lo,Lo,Hi,Lo,Hi,Lo,Hi, //4
Hi,Lo,Lo,Lo,Lo,Lo,Hi,Lo,Lo,Hi,Hi,Hi,Lo,Hi,Hi,Hi,Hi,Lo,Lo,Lo,Hi,Lo,Hi,Lo,
Lo,Lo,Lo,Lo,Lo,Hi,Lo,Lo,Hi,Hi,Hi,Lo,Hi,Hi,Hi,Hi,Lo,Lo,Lo,Hi,Lo,Hi,Lo,Hi,
Lo,Lo,Lo,Lo,Lo,Hi,Lo,Lo,Hi,Hi,Hi,Lo,Hi,Hi,Hi,Hi,Lo,Lo,Lo,Hi,Lo,Hi,Lo,Hi,
Lo,Lo,Lo,Lo,Lo,Hi,Lo,Lo,Hi,Hi,Hi,Lo,Hi,Hi,Hi,Hi,Lo,Lo,Lo,Hi,Lo,Hi,Lo,Hi,
Lo,Lo,Lo,Lo,Lo,Hi,Lo,Lo,Hi,Hi,Hi,Lo,Hi,Hi,Hi,Hi,Lo,Lo,Lo,Hi,Lo,Hi,Lo,Hi,
Lo,Lo,Lo,Lo,Lo,Hi,Lo,Lo,Hi,Hi,Hi,Lo,Hi,Hi,Hi,Hi,Lo,Lo,Lo,Hi,Lo,Hi,Lo,Hi,
Lo,Lo,Lo,Lo,Lo,Hi,Lo,Lo,Hi,Hi,Hi,Lo,Hi,Hi,Hi,Hi,Lo,Lo,Lo,Hi,Lo,Hi,Lo,Hi,
Lo,Lo,Lo,Lo,Lo,Hi,Lo,Lo,Hi,Hi,Hi,Lo,Hi,Hi,Hi,Hi,Lo,Lo,Lo,Hi,Lo,Hi,Lo,Hi,
};
uint8_t s_buf[LED*24+48]={
Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,
Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,
Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,
Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,
Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,
Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,
Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,
Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,
Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,
Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,
Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,
Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,
};
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_TIM3_Init(void);
static void MX_USART3_UART_Init(void);
static void MX_USART2_UART_Init(void);
MX_GPIO_Init();
MX_DMA_Init();
MX_TIM3_Init();
MX_USART3_UART_Init();
MX_USART2_UART_Init();
void convert_color(uint32_t color , uint16_t led_no)
{
for (int i=0; i<LED; i++)
{
buf[led_no*LED+i] = 57;
if ( color&(1<<((LED-1)-i)))
{
buf[led_no*LED+i] =Hi;
}
else
{
buf[led_no*LED+i] =Lo;
}
}
}
HAL_TIM_PWM_Stop_DMA(&htim3,TIM_CHANNEL_1);
HAL_TIM_PWM_Start_DMA(&htim3,TIM_CHANNEL_1,(uint32_t*)buf,LED*24+48);
while(hdma_tim3_ch1_trig.Instance->CNDTR>0);
HAL_Delay(3000);
char data[10];
memset(buf,0,LED*12+48);
while (1) {
for (int i=0;i<4;i++)
for (int i=0;i<12;i++)
{
convert_color(rand(),i);
}
HAL_TIM_PWM_Start_DMA(&htim3,TIM_CHANNEL_1,(uint32_t*)buf,LED*12+48);
while(hdma_tim3_ch1_trig.Instance->CNDTR>0);
HAL_Delay(100);
HAL_Delay(1000);
}
}
DMA / TIMER TRIG를 활용해서 LED 배열에 있는 걸 랜덤하게 색을 바꿔주는 코드
https://youtube.com/shorts/P4mBGVFVmnA <- LED
시연 영상 보고 싶음 보셈2. UART 통신
UART를 활용하여 라즈베리파이로 부터 사용자에게 입력데이터를 전달받음(LED를 킬 것인지 끌 것인지) 이러한 데이터를 받으면 STM32를 활용하여 RGB LED를 제어한다.
2-2 설정
UART는 UART3과 UART2 두개를 사용한다. 이유는 한개로 하였을 때 통신이 불완전 했기 때문이다.
UART 2와 3은 설정이 같다.
코드
#include <stdlib.h> #include <string.h> void led_off(uint16_t led_no) { for (int i=0; i<24; i++) { buf[led_no*24+i] = Lo; } } void led_on(uint16_t led_no) { for (int i=0; i<24; i++) { buf[led_no*24+i] = Hi; } } int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_DMA_Init(); MX_TIM3_Init(); MX_USART3_UART_Init(); MX_USART2_UART_Init() HAL_TIM_PWM_Stop_DMA(&htim3,TIM_CHANNEL_1); HAL_TIM_PWM_Start_DMA(&htim3,TIM_CHANNEL_1,(uint32_t*)buf,LED*24+48); while(hdma_tim3_ch1_trig.Instance->CNDTR>0); HAL_Delay(3000); char data[10]; memset(buf,0,LED*24+48); while (1) { HAL_UART_Receive(&huart3, (uint8_t *)data,1,0xFFFF); // HAL_UART_Transmit(&huart2, data, sizeof(data), 1000); if (data[0] == '0') { HAL_UART_Transmit(&huart2, "0", sizeof("0"), 1000); // HAL_TIM_PWM_Start_DMA(&htim3,TIM_CHANNEL_1,(uint32_t*)s_buf,LED*24+48); for ( int i=0; i<12; i++ ) { led_off(i); } } else if (data[0] == '1') { HAL_UART_Transmit(&huart2, "1", sizeof("1"), 1000); // HAL_TIM_PWM_Start_DMA(&htim3,TIM_CHANNEL_1,(uint32_t*)buf,LED*24+48); for ( int j=0; j<12; j++ ) { led_on(j); } } HAL_TIM_PWM_Start_DMA(&htim3,TIM_CHANNEL_1,(uint32_t*)buf,LED*24+48); while(hdma_tim3_ch1_trig.Instance->CNDTR>0); HAL_Delay(500); } }
HAL_UART_Receive
: UART로 온 신호를 받음 그리고 data라는 곳에다가 저장을 함.
HAL_UART_Transmit
: UART신호를 제대로 받았는지 확인을 위해 출력을 한다.
HAL_TIM_PWM_Start_DMA
: CCRx 레지스터에 전송하는 역할0이라는 신호를 UART에서 받으면 buf 배열에다가 0을 넣고 1이 들어오면 buf 배열에다가 1을 넣음
라즈베리파이(백엔드)
1. 카메라 제어
camera.py
from picamera2 import Picamera2 # pip install picamera2 import subprocess from flask import jsonify def plant_picture(): picam2 = Picamera2() camera_config = picam2.create_preview_configuration() picam2.configure(camera_config) picam2.start() # /home/pi/CUCU_FE/COUQUE-DASSE-FRONT/front/public/myPlnat # /home/pi/imgs/ p = subprocess.check_output("cd /home/pi/CUCU_FE/COUQUE-DASSE-FRONT/front/public/myPlant/; ls -l | grep ^- | wc -l; cd ../..",shell=True, encoding='utf-8') p =str(p) p = p[:len(p)-1] print(p) # picam2.capture_file(f"../imgs/pic{p}.jpg") picam2.capture_file(f"/home/pi/CUCU_FE/COUQUE-DASSE-FRONT/front/public/myPlant/pic{p}.jpg") # pic_path = f"/home/pi/imgs/pic{p}.jpg" pic_path = f"./myPlant/pic{p}.jpg" picam2.close() return str(pic_path) # return jsonify({'path':pic_path}) # ./static/imgs/pic{p}.jpg #, p
함수를 호출을 하면 사진을 찍고 사진을 저장한 다음에 그러한 저장 경로를 반환함
uart.py
import time import serial ser1 = serial.Serial( port='/dev/ttyAMA3', baudrate=115200, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=1, dsrdtr=False ) def send_string(degree): ser1.write(degree.encode())
uart 초기 설정이랑 함수를 호출시 매개변수를 받아 UART 통신으로 stm32로 보냄
app.py
from flask import Flask , render_template , Response from flask import request from flask_cors import CORS # pip install flask-cors from camera import * from uart import * app = Flask(__name__,static_url_path='/static') CORS( app, resources={r"/plant/*": {"origins":"*"}}, supports_credentials=True ) @app.route('/plant/test',methods=['GET']) def hello(): return 'hello flask' @app.route('/plant/path',methods=['GET','POST']) def take_picture(): result = plant_picture() return result @app.route('/plant/led',methods=['GET']) def ledc_ontroll(): is_led = "" led_value = request.args.get('val','test') if ( str(led_value) == 'true'): is_led = "1" elif ( str(led_value) == 'false'): is_led = "0" print(is_led) send_string(is_led) return led_value def main(): app.debug = True app.run(host="IP", port="PORT NUMBER") if __name__ == '__main__': main()
결과물
결과물 사진 넣기 동영상도 넣기
프론트
![]()
프로젝트 역할
백엔드 , 하드웨어 제어 , 팀장
느낀점 : 맨 처음에는 어렵다고 느끼고 막막하였지만 해결하는 과정에서 재미를 느꼈다. 또한 팀장을 맡게 되어 책임감이 생겨서 각자 할 수 있는 것들을 잘 분배하여 모두가 다같이 프로젝트에 참여하게 되어서 뿌듯했다. 팀장의 역할이 굉장히 중요하다고 느꼈고 에러를 해결해 나가는 과정에서 팀원들간의 소통 과 협업 등이 중요하다고 강하게 느꼈다 .
github
혹시 LED 납댐 어디에다가 하셨나요??? 보드는 몇번 핀에다가 연결 하셨나요???