[Arduino-IDE] Seeed Studio XIAO ESP32S3 Sense 기본 예제 및 에러 조치

프로그래밍/C, C++|2024. 11. 1. 18:48
반응형

Seeed Studio XIAO ESP32S3 Sense는 카메라(OV2640)와 디지털 마이크가 내장된 ESP32-S3 기반 개발 보드로, Wi-Fi를 통해 영상 스트리밍이 가능합니다.

 

 

1. Arduino IDE 기본 세팅

 

Arduino IDE 실행 > 파일 > 기본 설정 > (중간) Language 에 한국어 선택 후 확인.

 

Arduino IDE 실행 > 파일 > 기본 설정 > (맨아래) 추가 보드 관리자 URL 에 아래 내용입력 후 확인.

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

 

Arduino IDE 실행 > 도구 > 보드 > 보드매니저 실행해서 아래 두개 설치

- Arduino ESP32 Boards

- esp32

 

Arduino IDE 실행 > 도구 > 보드 > esp32 > ESP32S3 Dev Module Octal (WROOM2) 선택

 

USB 에 기기 연결 후, 상단 셀렉트 옵션에서 기기 선택해 놓습니다.

 

 

2. 시리얼 포트 접근 권한 추가

 

리눅스 시스템에서 시리얼 포트에 대한 접근 권한을 주어야 합니다.

다음과 같이 사용자를 dialout 그룹에 추가합니다.

명령을 실행한 후 시스템에서 로그아웃했다가 다시 로그인해야 변경사항이 적용됩니다. (생략 가능)

$ sudo usermod -a -G dialout $USER

 

시리얼 포트에 직접 권한 부여하는 방법도 있습니다.

$ sudo chmod 666 /dev/ttyACM0

하지만 이 방법은 임시적인 해결책으로, 재부팅 후에는 다시 권한을 설정해야 합니다.

 

 

3. 예제 입력 및 컴파일

 

Arduino IDE에는 여러가지 예제가 준비되어 있습니다.

ESP32S3 카메라를 올바르게 사용하기 위해 기본 제공되는 예제를 사용해 봅니다.

 

Arduino IDE 실행 > 파일 > 예제 > ESP32 > Camera > CameraWebServer 선택

 

열려진 예제 코드에서 WiFi 설정만 수정합니다.
const char* ssid = "CDH";                   // Wi-Fi SSID
const char* password = "12345678";  // Wi-Fi 비밀번호

보드 선택이 "ESP32S3 Dev Module" 또는 "ESP32S3 Sense"로 설정되어 있는지 확인합니다.
업로드를 실행 합니다.

 

아래와 같은 결과가 출력되면 성공한 것입니다.

 

[출력]

스케치는 프로그램 저장 공간 1000446 바이트(76%)를 사용. 최대 1310720 바이트.
전역 변수는 동적 메모리 62908바이트(19%)를 사용, 264772바이트의 지역변수가 남음.  최대는 327680 바이트.
esptool.py v4.8.1
Serial port /dev/ttyACM0
Connecting...
Chip is ESP32-S3 (QFN56) (revision v0.2)
Features: WiFi, BLE, Embedded PSRAM 8MB (AP_3v3)
Crystal is 40MHz
MAC: d8:3b:da:45:d2:7c
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
Changed.
Configuring flash size...
Flash will be erased from 0x00000000 to 0x00004fff...
Flash will be erased from 0x00008000 to 0x00008fff...
Flash will be erased from 0x0000e000 to 0x0000ffff...
Flash will be erased from 0x00010000 to 0x00104fff...
Compressed 18976 bytes to 12282...
Writing at 0x00000000... (100 %)
Wrote 18976 bytes (12282 compressed) at 0x00000000 in 0.3 seconds (effective 499.2 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 134...
Writing at 0x00008000... (100 %)
Wrote 3072 bytes (134 compressed) at 0x00008000 in 0.0 seconds (effective 568.3 kbit/s)...
Hash of data verified.
Compressed 8192 bytes to 47...
Writing at 0x0000e000... (100 %)
Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.1 seconds (effective 756.9 kbit/s)...
Hash of data verified.
Compressed 1000592 bytes to 653189...
Writing at 0x00010000... (2 %)
Writing at 0x0001c4b8... (5 %)
Writing at 0x000253f6... (7 %)
Writing at 0x0002926d... (10 %)
Writing at 0x00030be0... (12 %)
Writing at 0x0003b4c8... (15 %)
Writing at 0x000449a9... (17 %)
Writing at 0x0004a26a... (20 %)
Writing at 0x0004f8be... (22 %)
Writing at 0x0005531c... (25 %)
Writing at 0x0005aabf... (27 %)
Writing at 0x0005fd0b... (30 %)
Writing at 0x00065104... (32 %)
Writing at 0x0006a55c... (35 %)
Writing at 0x0006fc7e... (37 %)
Writing at 0x00075228... (40 %)
Writing at 0x0007a3d1... (42 %)
Writing at 0x0007f636... (45 %)
Writing at 0x00084d7b... (47 %)
Writing at 0x0008aafd... (50 %)
Writing at 0x0009111e... (52 %)
Writing at 0x0009695f... (55 %)
Writing at 0x0009be10... (57 %)
Writing at 0x000a13d3... (60 %)
Writing at 0x000a6810... (62 %)
Writing at 0x000ab6c9... (65 %)
Writing at 0x000b0853... (67 %)
Writing at 0x000b5c6b... (70 %)
Writing at 0x000baf83... (72 %)
Writing at 0x000bffbe... (75 %)
Writing at 0x000c5188... (77 %)
Writing at 0x000cac39... (80 %)
Writing at 0x000d07d9... (82 %)
Writing at 0x000d5cc7... (85 %)
Writing at 0x000e0b33... (87 %)
Writing at 0x000e64ab... (90 %)
Writing at 0x000eb3f0... (92 %)
Writing at 0x000f35f3... (95 %)
Writing at 0x000f92d7... (97 %)
Writing at 0x000fee95... (100 %)
Wrote 1000592 bytes (653189 compressed) at 0x00010000 in 6.9 seconds (effective 1154.1 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting with RTC WDT...

 

[ 에러 ]

/dev/ttyACM0 가 보였다 안보였다 하는 증상은 Arduino IDE 에서 포트가 보였다 안보였다 하는 증상과 같습니다.

이는 업로드를 이미 했거나, 하는중 오류가 발생하였거나 기타 등등의 문제로 인해 생기는데,

해결책은 아래와 같습니다.

 

[ 해결 ]

데이터 케이블과 ESP32S3 Sense (기기) 와 분리합니다.

C-Type 머리가 보이게, 그리고 위로 올린 방향으로 두면 C-Type 오른쪽으로 보이는 버튼이 BOOT 버튼입니다.

BOOT 버튼을 누른채 데이터 케이블을 연결하면 불이 깜빡이며, 멈추었을때 손을 떼면 초기화 됩니다.

초기화 된 상태에서 다시 케이블을 분리하면 원래대로 돌아갑니다.

그러므로 연결된 상태 그대로 소스코드를 수정하고 업로드 해야 합니다.

 

※ BootLoader 모드란?
- 공장 초기화가 아닌, 새로운 펌웨어를 강제로 업로드할 수 있도록 하는 모드 

- 기존의 프로그램이 손상되었거나 업로드가 실패할 때, 이 모드를 통해 새로운 펌웨어를 강제로 설치 가능 

- 일반적인 운영 중에는 사용되지 않으며, 포트 인식 오류나 업로드 문제 해결 시 사용

 

[ 에러 ]

업로드시 아래와 같은 에러메세지가 출력된다면, 현재 사용자에게 장치 접근 권한을 추가해야 합니다.

 

스케치는 프로그램 저장 공간 1000446 바이트(76%)를 사용. 최대 1310720 바이트. 전역 변수는 동적 메모리 62908바이트(19%)를 사용, 264772바이트의 지역변수가 남음. 최대는 327680 바이트. esptool.py v4.8.1 Serial port /dev/ttyACM0 A fatal error occurred: Could not open /dev/ttyACM0, the port is busy or doesn't exist. ([Errno 13] could not open port /dev/ttyACM0: [Errno 13] Permission denied: '/dev/ttyACM0') Hint: Try to add user into dialout or uucp group. Failed uploading: uploading error: exit status 2

 

[ 해결 ]

# sudo usermod -a -G dialout $USER

그런 다음 로그아웃, 로그인없이 적용하기 위해서 현재 터미널에서 새 그룹 권한을 바로 적용합니다.

# newgrp dialout

 

이제 android-ide 를 실행하면  /dev/ttyACM0 장치에 대한 접근권한이 생깁니다.

 

반응형

댓글()

[C] 자신과 동일한 프로세스 이름이 가동중인지 확인하는 코드 (중복 실행 차단)

프로그래밍/C, C++|2024. 8. 27. 16:28
반응형

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>

int is_another_instance_running(const char *process_name, pid_t current_pid) {
    DIR *dir;
    struct dirent *entry;
    FILE *fp;
    char path[256], cmdline[256];

    dir = opendir("/proc");
    if (dir == NULL) {
        perror("opendir");
        return 0;
    }

    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_DIR && atoi(entry->d_name) > 0) {
            snprintf(path, sizeof(path), "/proc/%s/cmdline", entry->d_name);
            fp = fopen(path, "r");
            if (fp != NULL) {
                if (fgets(cmdline, sizeof(cmdline), fp) != NULL) {
                    // 프로세스 이름이 같고 현재 프로세스가 아닌 경우
                    if (strstr(cmdline, process_name) != NULL && atoi(entry->d_name) != current_pid) {
                        fclose(fp);
                        closedir(dir);
                        return 1;  // 다른 인스턴스가 실행 중임
                    }
                }
                fclose(fp);
            }
        }
    }

    closedir(dir);
    return 0;  // 다른 인스턴스가 실행 중이지 않음
}

int main(int argc, char *argv[]) {
    pid_t current_pid = getpid();  // 현재 프로세스의 PID 가져오기
    const char *process_name = argv[0];  // 자신의 실행 파일 이름

    // 실행 파일 이름에서 경로 제거 (예: ./myprogram -> myprogram)
    const char *base_name = strrchr(process_name, '/');
    if (base_name) {
        base_name++;  // '/' 이후의 문자열을 사용
    } else {
        base_name = process_name;  // 경로가 없는 경우 원래 이름 사용
    }

    if (is_another_instance_running(base_name, current_pid)) {
        printf("이미 가동 중입니다. 프로그램을 종료합니다.\n");
    } else {
        printf("미가동 상태입니다. 프로그램을 시작합니다.\n");
        // 여기에 프로그램의 메인 코드를 작성
        while (1) {
            sleep(10);  // 예시로 무한 대기
        }
    }

    return 0;
}

반응형

댓글()

[C++] 파일쓰기 예제

프로그래밍/C, C++|2023. 12. 11. 17:02
반응형

#include<fstream>
#include<iostream>
#include<string>
 
using namespace std;
 
int main() {
    fstream my_file;
    my_file.open("a.txt", ios::out);    // 이 파일이 생성됩니다.
    my_file << "test" << endl;           // test 라는 내용이 들어가며
    my_file.write("12345", 5);           // 이렇게도 추가할 수 있습니다.
    my_file.close();
}

 

 

* 참고로 위 코드는 반복 실행시 계속 새로운 파일로 쓰이게 되며,

파일이 있을때 내용을 추가하고자 할경우 아래와 같이 ios::app (append) 플래그를 사용하면 됩니다.

my_file.open("a.txt", ios::out | ios::app);

 

반응형

댓글()

C/C++ 프로그레스바 (ProgressBar)

프로그래밍/C, C++|2023. 6. 16. 07:57
반응형

C/C++의 콘솔 환경에서 프로그레스바 (진행바) 구현 소스입니다.

아래와 같이 심플하게 개수, 프로그레스바, 진행률 이 출력됩니다.

 

10/10 [==================================================] 100%

 

#include <stdio.h>
#include <stdlib.h>  
#include <windows.h> // Sleep 함수 

int main() {
        const char bar = '='; // 프로그레스바 문자  
        const char blank = ' '; // 비어있는 프로그레스바 문자  
        const int LEN = 20; // 프로그레스바 길이  
        const int MAX = 1000; // 진행작업 최대값 
        const int SPEED = 50; // 카운트 증가 대기시간  
        int count = 0; // 현재 진행된 작업  
        int i; // 반복문 전용 변수  
        float tick = (float)100/LEN; // 몇 %마다 프로그레스바 추가할지 계산 
        printf("%0.2f%% 마다 bar 1개 출력\n\n", tick); 
        int bar_count; // 프로그레스바 갯수 저장 변수  
        float percent; // 퍼센트 저장 변수  
        while(count <= MAX) {
                printf("\r%d/%d [", count, MAX); // 진행 상태 출력  
                percent = (float)count/MAX*100; // 퍼센트 계산  
                bar_count = percent/tick; // 프로그레스바 갯수 계산  
                for(i=0; i<LEN; i++) { // LEN길이의 프로그레스바 출력  
                        if(bar_count > i) { // 프로그레스바 길이보다 i가 작으면 
                                printf("%c", bar);
                        } else { // i가 더 커지면  
                                printf("%c", blank);
                        }
                }
                printf("] %0.2f%%", percent); // 퍼센트 출력  
                count++; // 카운트 1증가  
                Sleep(SPEED); // SPEEDms 대기  
        }
        printf(" done!\n\n");
        system("pause"); // 프로그램 종료 전 일시정지  
        return 0; 
}

 

1000개의 전체 작업량 중 1개가 완료되었다면 진행률은 0.1%가 됩니다.
현재 진행량/전체 진행량 * 100 = 진행률(%)
100분율 계산법입니다.
해당 연산은 코드의 19행에서 진행하고 있습니다.
현재 진행량은 코드상에서 count 변수
전체 진행향은 코드상에서 MAX 변수입니다.

진행률을 계산했으면 해당 진행률을 기준으로 프로그레스바(진행바)를 출력해야합니다.
100(%)/프로그레스바 길이 = 몇 %마다 프로그레스바 1개 출력
만약 프로그레스바의 길이가 20이라고 하면
100/20 = 5
[====================] 100%
위의 모습일겁니다.

길이는 고정되어있음으로 진행률 퍼센트에 따라 = 문자를 출력해줘야 하죠
코드의 13행에서 해당 계산을 진행하고 있습니다.
계산 후 tick 이라는 변수에 저장해두었습니다.

20길이의 프로그레스바는 5% 마다 = 한개를 출력합니다.
10%라고 하면 == 를 출력하겠죠?

17~31행의 while 문은 0~전체 진행량까지 반복하는 반복문입니다.
19행에서 매번 반복마다 진행률(%)을 계산하여
20행에서 프로그레스바 = 문자를 몇개 출력할지 계산한 후
그 아래 21행 for문에서 출력을 합니다.

for문은 0~LEN 까지 반복을 하는데 LEN은 프로그레스바의 길이가 저장되있는 변수이름입니다.
20이라고 가정하면 0~20까지 반복하계되죠
bar_count는 20행에서 현재 %는 몇개의 =문자를 출력할지 저장되어있습니다.

만약 프로그레스바 길이가 20이고 진행률이 7%라고 가정합시다.

1 - 13행처럼 먼저 몇 %마다 =문자를 출력할지 계산
100/20 = 5(%)
tick = 5

2 - bar_count에 현재 퍼센트는 몇개의 =를 출력할지 계산
percent/tick = 갯수
7/5 = 1(나머지 버림)
bar_count = 1

3 - for문에서 출력
LEN이 20이므로 i = 0~20
if(bar_count > i) 
0~20까지 i가 증가하면서 bar_count와 비교하여 출력
bar_count는 현재 1이 저장되어있으므로 i가 0일때만 참
20번 반복하면서 =하나를 출력하게 되고
거짓인 경우에는 else 로 가서 공백을 출력합니다.

4 - for문으로 출력 후 퍼센트 출력 및 count 증가
count(현재 진행량)를 1 증가

위의 과정을 현재 진행량~전체 진행량까지 반복하여 100%가 되면 종료합니다.
출력하는데 왜 이어서 출력이 되지않고 원래 위치 그대로에서 출력될까요?
그 문제는 18행에 있습니다.
printf("\r")

\r 이스케이프 시퀀스는 해당 라인의 첫 번째 위치로 이동합니다.
첫 번째로 이동한 후 다시 출력을 하게되어 위치가 바뀌지않고 진행되는이유입니다.

 

[출처] https://geundung.dev/43

 

 

반응형

댓글()

[C/C++] int 를 char 또는 const char* 로 변환하기

프로그래밍/C, C++|2022. 6. 30. 13:13
반응형

숫자 뒤에 0 을 붙이면 문자로 인식합니다.

 

const int pos = 100;

const char* charpos = pos+"0";

 

반응형

댓글()

C++ 프로그램 중복 실행 방지 (윈도우 기반)

프로그래밍/C, C++|2021. 5. 18. 13:16
반응형

HANDLE Mutex;
const char ProgMutex[] = "Sysdocu"; // 프로젝트명
if ((Mutex = OpenMutex(MUTEX_ALL_ACCESS, false, ProgMutex)) == NULL)
    Mutex = CreateMutex(NULL, true, ProgMutex);
else {
    MessageBox(NULL, "이미 실행중입니다.", "알림", MB_OK);
    return 0;
}

 

 

반응형

댓글()

C++ 에서 구동 파일의 절대 경로 확인하기 (windows)

프로그래밍/C, C++|2021. 5. 17. 14:29
반응형

1. 구동 파일 절대 경로 출력 (파일)

 

char cCurrentPath[FILENAME_MAX];
GetModuleFileName(NULL, cCurrentPath, MAX_PATH);
cCurrentPath[sizeof(cCurrentPath) - 1] = '\0';
printf("The current working file is %s\n", cCurrentPath);

 

 

2. 구동 파일 절대 경로 출력 (디렉토리)

- 위 소스에서 코드 한줄만 더 추가하면 파일명이 제외된 디렉토리만 출력됩니다.

PathRemoveFileSpec(cCurrentPath);

printf("The current working directory is %s\n", cCurrentPath);

 

반응형

댓글()

(에러) 인수 1을(를) 'ATL::CString'에서 'const char *'(으)로 변환할 수 없습니다.

프로그래밍/C, C++|2021. 5. 14. 14:15
반응형

코드나 환경에 따라 아래와 같은 에러가 출력될 수 있습니다.

저는 디렉토리 이동 함수를 사용할때 메세지가 출력 되었습니다.

 

(에러)

'int _chdir(const char *)': 인수 1을(를) 'ATL::CString'에서 'const char *'(으)로 변환할 수 없습니다.

 

(해결)

이경우 아래와 같이 해주세요.

_chdir((char*)(LPCTSTR)strFolderPath);

 

 

반응형

댓글()

Windows C++ 로 시스템 DISK 사용률 출력하기

프로그래밍/C, C++|2021. 4. 22. 09:33
반응형

BOOL  fResult;

unsigned __int64 i64FreeBytesToCaller,

    i64TotalBytes,

    i64FreeBytes;

fResult = GetDiskFreeSpaceEx(L"C:",

    (PULARGE_INTEGER)&i64FreeBytesToCaller,

    (PULARGE_INTEGER)&i64TotalBytes,

    (PULARGE_INTEGER)&i64FreeBytes);

if (fResult)

{

    printf("Available space to caller = %I64u MB\n",

        i64FreeBytesToCaller / (1024 * 1024));

    printf("Total space               = %I64u MB\n",

        i64TotalBytes / (1024 * 1024));

    printf("Free space on drive       = %I64u MB\n",

        i64FreeBytes / (1024 * 1024));

}

 

[출처] https://stackoverflow.com/questions/11917946/how-do-i-get-available-disk-space-from-windows-using-c

반응형

댓글()

Windows C++ 로 시스템 메모리(MEM) 사용률 출력하기

프로그래밍/C, C++|2021. 4. 22. 09:28
반응형

 

MEMORYSTATUSEX memInfo;

memInfo.dwLength = sizeof(MEMORYSTATUSEX);

GlobalMemoryStatusEx(&memInfo);

DWORDLONG totalPhysMem = memInfo.ullTotalPhys; // 전체 메모리

DWORDLONG availPhysMem = memInfo.ullAvailPhys; // 남은 메모리

printf("MEM : %I64u %I64u\n", totalPhysMem / 1024, availPhysMem / 1024); // KB 로 출력

 

[참고] https://ospace.tistory.com/514

반응형

댓글()

Windows C++ 로 시스템 CPU 사용률 출력하기

프로그래밍/C, C++|2021. 4. 22. 08:53
반응형

#include <Windows.h>

#include <iostream>

using namespace std;

static float CalculateCPULoad();

static unsigned long long FileTimeToInt64();

float GetCPULoad();

int main()

{

    printf("%.1f", GetCPULoad()); // 소수점 1자리까지 출력

    return 0;

}

static float CalculateCPULoad(unsigned long long idleTicks, unsigned long long totalTicks)

{

    static unsigned long long _previousTotalTicks = 0;

    static unsigned long long _previousIdleTicks = 0;

    unsigned long long totalTicksSinceLastTime = totalTicks - _previousTotalTicks;

    unsigned long long idleTicksSinceLastTime = idleTicks - _previousIdleTicks;

    float ret = 1.0f - ((totalTicksSinceLastTime > 0) ? ((float)idleTicksSinceLastTime) / totalTicksSinceLastTime : 0);

    _previousTotalTicks = totalTicks;

    _previousIdleTicks = idleTicks;

    return ret;

}

static unsigned long long FileTimeToInt64(const FILETIME& ft) { return (((unsigned long long)(ft.dwHighDateTime)) << 32) | ((unsigned long long)ft.dwLowDateTime); }

// Returns 1.0f for "CPU fully pinned", 0.0f for "CPU idle", or somewhere in between

// You'll need to call this at regular intervals, since it measures the load between

// the previous call and the current one.  Returns -1.0 on error.

float GetCPULoad()

{

    FILETIME idleTime, kernelTime, userTime;

    return GetSystemTimes(&idleTime, &kernelTime, &userTime) ? CalculateCPULoad(FileTimeToInt64(idleTime), FileTimeToInt64(kernelTime) + FileTimeToInt64(userTime)) : -1.0f;

}

 

[출처] https://stackoverflow.com/questions/23143693/retrieving-cpu-load-percent-total-in-windows-with-c

 

반응형

댓글()