init freenove esp32-s3-wroom cam docu
parent
7148425bd6
commit
cd63bcb8ad
18
README.md
18
README.md
|
|
@ -32,15 +32,15 @@ What we need for functionality:
|
|||
<a name="supported_boards"></a>
|
||||
## Supported boards
|
||||
|
||||
| Board name | Support | Stream | Micro SD | FLASH LED | FW update | DHT22/DHT11 | Documentation |
|
||||
|---------------------------|-------------|--------|----------|-----------|-----------|-------------|----------------------------------------------|
|
||||
| Ai-Thinker ESP32-cam | Full | Yes | Yes | Board/Ext | Yes | Yes | [ here ](doc/AI_Thinker-ESP32-cam/README.md) |
|
||||
| ESP32-S3-EYE 2.2 | Full | Yes | Yes | External | Yes | Yes | [ here ](doc/ESP32-S3-EYE-22/README.md) |
|
||||
| Freenove ESP32-Wrover cam | Full | Yes | No | External | Yes | Yes | [ here ](doc/ESP32-Wrover-dev/README.md) |
|
||||
| Freenove ESP32-S3-Wroom | in Progress | | | | | | |
|
||||
| ESP32-S3-DEV-CAM | in Progress | | | External | | | [ here ](doc/ESP32-S3-DEV-CAM/README.md) |
|
||||
| Seeed Studio XIAO ESP32S3 | Full | Yes | Yes | External | Yes | Yes | [ here ](doc/XIAO_ESP32S3/README.md) |
|
||||
| ESP32-S3-CAM | Full | Yes | Yes | Board/Ext | Yes | Yes | [ here ](doc/ESP32-S3-CAM/README.md) |
|
||||
| Board name | Support | Stream | Micro SD | FLASH LED | FW update | DHT22/DHT11 | Documentation |
|
||||
|---------------------------|-------------|--------|----------|-----------|-----------|-------------|------------------------------------------------|
|
||||
| Ai-Thinker ESP32-cam | Full | Yes | Yes | Board/Ext | Yes | Yes | [ here ](doc/AI_Thinker-ESP32-cam/README.md) |
|
||||
| ESP32-S3-EYE 2.2 | Full | Yes | Yes | External | Yes | Yes | [ here ](doc/ESP32-S3-EYE-22/README.md) |
|
||||
| Freenove ESP32-Wrover cam | Full | Yes | No | External | Yes | Yes | [ here ](doc/ESP32-Wrover-dev/README.md) |
|
||||
| Freenove ESP32-S3-Wroom | in Progress | | | | | | [ here ](doc/Freenove ESP32-S3-Wroom/README.md | |
|
||||
| ESP32-S3-DEV-CAM | in Progress | | | External | | | [ here ](doc/ESP32-S3-DEV-CAM/README.md) |
|
||||
| Seeed Studio XIAO ESP32S3 | Full | Yes | Yes | External | Yes | Yes | [ here ](doc/XIAO_ESP32S3/README.md) |
|
||||
| ESP32-S3-CAM | Full | Yes | Yes | Board/Ext | Yes | Yes | [ here ](doc/ESP32-S3-CAM/README.md) |
|
||||
|
||||
The compiled firmware for each supported board is published with every release.
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 545 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,20 @@
|
|||
/**********************************************************************
|
||||
* Filename : Blink
|
||||
* Description : Make an led blinking.
|
||||
* Auther : www.freenove.com
|
||||
* Modification: 2022/10/19
|
||||
**********************************************************************/
|
||||
#define LED_BUILTIN 2
|
||||
// the setup function runs once when you press reset or power the board
|
||||
void setup() {
|
||||
// initialize digital pin LED_BUILTIN as an output.
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
}
|
||||
|
||||
// the loop function runs over and over again forever
|
||||
void loop() {
|
||||
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
|
||||
delay(1000); // wait for a second
|
||||
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
|
||||
delay(1000); // wait for a second
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/**********************************************************************
|
||||
Filename : SerialPrinter
|
||||
Description : Use UART send some data to PC, and show them on serial monitor.
|
||||
Auther : www.freenove.com
|
||||
Modification: 2022/10/20
|
||||
**********************************************************************/
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("ESP32S3 initialization completed!");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.printf("Running time : %.1f s\r\n", millis() / 1000.0f);
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/**********************************************************************
|
||||
Filename : SerialRW
|
||||
Description : Use UART read and write data between ESP32 and PC.
|
||||
Auther : www.freenove.com
|
||||
Modification: 2022/10/20
|
||||
**********************************************************************/
|
||||
String inputString = ""; //a String to hold incoming data
|
||||
bool stringComplete = false; // whether the string is complete
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println(String("\nESP32S3 initialization completed!\r\n")
|
||||
+ String("Please input some characters,\r\n")
|
||||
+ String("select \"Newline\" below and Ctrl + Enter to send message to ESP32S3. \r\n"));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (Serial.available()) { // judge whether data has been received
|
||||
char inChar = Serial.read(); // read one character
|
||||
inputString += inChar;
|
||||
if (inChar == '\n') {
|
||||
stringComplete = true;
|
||||
}
|
||||
}
|
||||
if (stringComplete) {
|
||||
Serial.printf("inputString: %s \r\n", inputString);
|
||||
inputString = "";
|
||||
stringComplete = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/**********************************************************************
|
||||
Filename : BLE_USART
|
||||
Description : Esp32 communicates with the phone by BLE and sends incoming data via a serial port
|
||||
Auther : www.freenove.com
|
||||
Modification: 2024/07/01
|
||||
**********************************************************************/
|
||||
#include "BLEDevice.h"
|
||||
#include "BLEServer.h"
|
||||
#include "BLEUtils.h"
|
||||
#include "BLE2902.h"
|
||||
|
||||
BLECharacteristic *pCharacteristic;
|
||||
bool deviceConnected = false;
|
||||
uint8_t txValue = 0;
|
||||
long lastMsg = 0;
|
||||
String rxload="Test\n";
|
||||
|
||||
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
|
||||
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
|
||||
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
|
||||
|
||||
class MyServerCallbacks: public BLEServerCallbacks {
|
||||
void onConnect(BLEServer* pServer) {
|
||||
deviceConnected = true;
|
||||
};
|
||||
void onDisconnect(BLEServer* pServer) {
|
||||
deviceConnected = false;
|
||||
//pServer->getAdvertising()->start(); //Reopen the pServer and wait for the connection.
|
||||
}
|
||||
};
|
||||
|
||||
class MyCallbacks: public BLECharacteristicCallbacks {
|
||||
void onWrite(BLECharacteristic *pCharacteristic) {
|
||||
String rxValue = pCharacteristic->getValue();
|
||||
if (rxValue.length() > 0) {
|
||||
rxload="";
|
||||
for (int i = 0; i < rxValue.length(); i++){
|
||||
rxload +=(char)rxValue[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void setupBLE(String BLEName){
|
||||
const char *ble_name=BLEName.c_str();
|
||||
BLEDevice::init(ble_name);
|
||||
BLEServer *pServer = BLEDevice::createServer();
|
||||
pServer->setCallbacks(new MyServerCallbacks());
|
||||
BLEService *pService = pServer->createService(SERVICE_UUID);
|
||||
pCharacteristic= pService->createCharacteristic(CHARACTERISTIC_UUID_TX,BLECharacteristic::PROPERTY_NOTIFY);
|
||||
pCharacteristic->addDescriptor(new BLE2902());
|
||||
BLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX,BLECharacteristic::PROPERTY_WRITE);
|
||||
pCharacteristic->setCallbacks(new MyCallbacks());
|
||||
pService->start();
|
||||
pServer->getAdvertising()->start();
|
||||
Serial.println("Waiting a client connection to notify...");
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
setupBLE("ESP32S3_Bluetooth");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
long now = millis();
|
||||
if (now - lastMsg > 100) {
|
||||
if (deviceConnected&&rxload.length()>0) {
|
||||
Serial.println(rxload);
|
||||
rxload="";
|
||||
}
|
||||
if(Serial.available()>0){
|
||||
String str=Serial.readString();
|
||||
const char *newValue=str.c_str();
|
||||
pCharacteristic->setValue(newValue);
|
||||
pCharacteristic->notify();
|
||||
}
|
||||
lastMsg = now;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/**********************************************************************
|
||||
Filename : SDMMC Test
|
||||
Description : The SD card is accessed using the SDMMC one-bit bus
|
||||
Auther : www.freenove.com
|
||||
Modification: 2022/10/28
|
||||
**********************************************************************/
|
||||
#include "sd_read_write.h"
|
||||
#include "SD_MMC.h"
|
||||
|
||||
#define SD_MMC_CMD 38 //Please do not modify it.
|
||||
#define SD_MMC_CLK 39 //Please do not modify it.
|
||||
#define SD_MMC_D0 40 //Please do not modify it.
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
|
||||
if (!SD_MMC.begin("/sdcard", true, true, SDMMC_FREQ_DEFAULT, 5)) {
|
||||
Serial.println("Card Mount Failed");
|
||||
return;
|
||||
}
|
||||
uint8_t cardType = SD_MMC.cardType();
|
||||
if(cardType == CARD_NONE){
|
||||
Serial.println("No SD_MMC card attached");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.print("SD_MMC Card Type: ");
|
||||
if(cardType == CARD_MMC){
|
||||
Serial.println("MMC");
|
||||
} else if(cardType == CARD_SD){
|
||||
Serial.println("SDSC");
|
||||
} else if(cardType == CARD_SDHC){
|
||||
Serial.println("SDHC");
|
||||
} else {
|
||||
Serial.println("UNKNOWN");
|
||||
}
|
||||
|
||||
uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
|
||||
Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);
|
||||
|
||||
listDir(SD_MMC, "/", 0);
|
||||
|
||||
createDir(SD_MMC, "/mydir");
|
||||
listDir(SD_MMC, "/", 0);
|
||||
|
||||
removeDir(SD_MMC, "/mydir");
|
||||
listDir(SD_MMC, "/", 2);
|
||||
|
||||
writeFile(SD_MMC, "/hello.txt", "Hello ");
|
||||
appendFile(SD_MMC, "/hello.txt", "World!\n");
|
||||
readFile(SD_MMC, "/hello.txt");
|
||||
|
||||
deleteFile(SD_MMC, "/foo.txt");
|
||||
renameFile(SD_MMC, "/hello.txt", "/foo.txt");
|
||||
readFile(SD_MMC, "/foo.txt");
|
||||
|
||||
testFileIO(SD_MMC, "/test.txt");
|
||||
|
||||
Serial.printf("Total space: %lluMB\r\n", SD_MMC.totalBytes() / (1024 * 1024));
|
||||
Serial.printf("Used space: %lluMB\r\n", SD_MMC.usedBytes() / (1024 * 1024));
|
||||
}
|
||||
|
||||
void loop(){
|
||||
delay(10000);
|
||||
}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
#include "sd_read_write.h"
|
||||
|
||||
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
|
||||
Serial.printf("Listing directory: %s\n", dirname);
|
||||
|
||||
File root = fs.open(dirname);
|
||||
if(!root){
|
||||
Serial.println("Failed to open directory");
|
||||
return;
|
||||
}
|
||||
if(!root.isDirectory()){
|
||||
Serial.println("Not a directory");
|
||||
return;
|
||||
}
|
||||
|
||||
File file = root.openNextFile();
|
||||
while(file){
|
||||
if(file.isDirectory()){
|
||||
Serial.print(" DIR : ");
|
||||
Serial.println(file.name());
|
||||
if(levels){
|
||||
listDir(fs, file.path(), levels -1);
|
||||
}
|
||||
} else {
|
||||
Serial.print(" FILE: ");
|
||||
Serial.print(file.name());
|
||||
Serial.print(" SIZE: ");
|
||||
Serial.println(file.size());
|
||||
}
|
||||
file = root.openNextFile();
|
||||
}
|
||||
}
|
||||
|
||||
void createDir(fs::FS &fs, const char * path){
|
||||
Serial.printf("Creating Dir: %s\n", path);
|
||||
if(fs.mkdir(path)){
|
||||
Serial.println("Dir created");
|
||||
} else {
|
||||
Serial.println("mkdir failed");
|
||||
}
|
||||
}
|
||||
|
||||
void removeDir(fs::FS &fs, const char * path){
|
||||
Serial.printf("Removing Dir: %s\n", path);
|
||||
if(fs.rmdir(path)){
|
||||
Serial.println("Dir removed");
|
||||
} else {
|
||||
Serial.println("rmdir failed");
|
||||
}
|
||||
}
|
||||
|
||||
void readFile(fs::FS &fs, const char * path){
|
||||
Serial.printf("Reading file: %s\n", path);
|
||||
|
||||
File file = fs.open(path);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file for reading");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.print("Read from file: ");
|
||||
while(file.available()){
|
||||
Serial.write(file.read());
|
||||
}
|
||||
}
|
||||
|
||||
void writeFile(fs::FS &fs, const char * path, const char * message){
|
||||
Serial.printf("Writing file: %s\n", path);
|
||||
|
||||
File file = fs.open(path, FILE_WRITE);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file for writing");
|
||||
return;
|
||||
}
|
||||
if(file.print(message)){
|
||||
Serial.println("File written");
|
||||
} else {
|
||||
Serial.println("Write failed");
|
||||
}
|
||||
}
|
||||
|
||||
void appendFile(fs::FS &fs, const char * path, const char * message){
|
||||
Serial.printf("Appending to file: %s\n", path);
|
||||
|
||||
File file = fs.open(path, FILE_APPEND);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file for appending");
|
||||
return;
|
||||
}
|
||||
if(file.print(message)){
|
||||
Serial.println("Message appended");
|
||||
} else {
|
||||
Serial.println("Append failed");
|
||||
}
|
||||
}
|
||||
|
||||
void renameFile(fs::FS &fs, const char * path1, const char * path2){
|
||||
Serial.printf("Renaming file %s to %s\n", path1, path2);
|
||||
if (fs.rename(path1, path2)) {
|
||||
Serial.println("File renamed");
|
||||
} else {
|
||||
Serial.println("Rename failed");
|
||||
}
|
||||
}
|
||||
|
||||
void deleteFile(fs::FS &fs, const char * path){
|
||||
Serial.printf("Deleting file: %s\n", path);
|
||||
if(fs.remove(path)){
|
||||
Serial.println("File deleted");
|
||||
} else {
|
||||
Serial.println("Delete failed");
|
||||
}
|
||||
}
|
||||
|
||||
void testFileIO(fs::FS &fs, const char * path){
|
||||
File file = fs.open(path);
|
||||
static uint8_t buf[512];
|
||||
size_t len = 0;
|
||||
uint32_t start = millis();
|
||||
uint32_t end = start;
|
||||
if(file){
|
||||
len = file.size();
|
||||
size_t flen = len;
|
||||
start = millis();
|
||||
while(len){
|
||||
size_t toRead = len;
|
||||
if(toRead > 512){
|
||||
toRead = 512;
|
||||
}
|
||||
file.read(buf, toRead);
|
||||
len -= toRead;
|
||||
}
|
||||
end = millis() - start;
|
||||
Serial.printf("%u bytes read for %u ms\r\n", flen, end);
|
||||
file.close();
|
||||
} else {
|
||||
Serial.println("Failed to open file for reading");
|
||||
}
|
||||
|
||||
file = fs.open(path, FILE_WRITE);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file for writing");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t i;
|
||||
start = millis();
|
||||
for(i=0; i<2048; i++){
|
||||
file.write(buf, 512);
|
||||
}
|
||||
end = millis() - start;
|
||||
Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
|
||||
file.close();
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef __SD_READ_WRITE_H
|
||||
#define __SD_READ_WRITE_H
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "FS.h"
|
||||
|
||||
|
||||
void listDir(fs::FS &fs, const char * dirname, uint8_t levels);
|
||||
void createDir(fs::FS &fs, const char * path);
|
||||
void removeDir(fs::FS &fs, const char * path);
|
||||
void readFile(fs::FS &fs, const char * path);
|
||||
void writeFile(fs::FS &fs, const char * path, const char * message);
|
||||
void appendFile(fs::FS &fs, const char * path, const char * message);
|
||||
void renameFile(fs::FS &fs, const char * path1, const char * path2);
|
||||
void deleteFile(fs::FS &fs, const char * path);
|
||||
void testFileIO(fs::FS &fs, const char * path);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/**********************************************************************
|
||||
Filename : WiFi Station
|
||||
Description : Connect to your router using ESP32
|
||||
Auther : www.freenove.com
|
||||
Modification: 2022/10/31
|
||||
**********************************************************************/
|
||||
#include <WiFi.h>
|
||||
|
||||
const char *ssid_Router = "********"; //Enter the router name
|
||||
const char *password_Router = "********"; //Enter the router password
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
delay(2000);
|
||||
Serial.println("Setup start");
|
||||
WiFi.begin(ssid_Router, password_Router);
|
||||
Serial.println(String("Connecting to ")+ssid_Router);
|
||||
while (WiFi.status() != WL_CONNECTED){
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("\nConnected, IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.println("Setup End");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/**********************************************************************
|
||||
Filename : WiFi AP
|
||||
Description : Set ESP32 to open an access point
|
||||
Auther : www.freenove.com
|
||||
Modification: 2022/10/31
|
||||
**********************************************************************/
|
||||
#include <WiFi.h>
|
||||
|
||||
const char *ssid_AP = "WiFi_Name"; //Enter the router name
|
||||
const char *password_AP = "12345678"; //Enter the router password
|
||||
|
||||
IPAddress local_IP(192,168,1,100);//Set the IP address of ESP32 itself
|
||||
IPAddress gateway(192,168,1,10); //Set the gateway of ESP32 itself
|
||||
IPAddress subnet(255,255,255,0); //Set the subnet mask for ESP32 itself
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
delay(2000);
|
||||
Serial.println("Setting soft-AP configuration ... ");
|
||||
WiFi.disconnect();
|
||||
WiFi.mode(WIFI_AP);
|
||||
Serial.println(WiFi.softAPConfig(local_IP, gateway, subnet) ? "Ready" : "Failed!");
|
||||
Serial.println("Setting soft-AP ... ");
|
||||
boolean result = WiFi.softAP(ssid_AP, password_AP);
|
||||
if(result){
|
||||
Serial.println("Ready");
|
||||
Serial.println(String("Soft-AP IP address = ") + WiFi.softAPIP().toString());
|
||||
Serial.println(String("MAC address = ") + WiFi.softAPmacAddress().c_str());
|
||||
}else{
|
||||
Serial.println("Failed!");
|
||||
}
|
||||
Serial.println("Setup End");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/**********************************************************************
|
||||
Filename : WiFi AP+Station
|
||||
Description : ESP32 connects to the user's router, turning on an access point
|
||||
Auther : www.freenove.com
|
||||
Modification: 2022/10/31
|
||||
**********************************************************************/
|
||||
#include <WiFi.h>
|
||||
|
||||
const char *ssid_Router = "********"; //Enter the router name
|
||||
const char *password_Router = "********"; //Enter the router password
|
||||
const char *ssid_AP = "WiFi_Name"; //Enter the router name
|
||||
const char *password_AP = "12345678"; //Enter the router password
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
Serial.println("Setting soft-AP configuration ... ");
|
||||
WiFi.disconnect();
|
||||
WiFi.mode(WIFI_AP);
|
||||
Serial.println("Setting soft-AP ... ");
|
||||
boolean result = WiFi.softAP(ssid_AP, password_AP);
|
||||
if(result){
|
||||
Serial.println("Ready");
|
||||
Serial.println(String("Soft-AP IP address = ") + WiFi.softAPIP().toString());
|
||||
Serial.println(String("MAC address = ") + WiFi.softAPmacAddress().c_str());
|
||||
}else{
|
||||
Serial.println("Failed!");
|
||||
}
|
||||
|
||||
Serial.println("\nSetting Station configuration ... ");
|
||||
WiFi.begin(ssid_Router, password_Router);
|
||||
Serial.println(String("Connecting to ")+ ssid_Router);
|
||||
while (WiFi.status() != WL_CONNECTED){
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("\nConnected, IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.println("Setup End");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/**********************************************************************
|
||||
Filename : WiFi Client
|
||||
Description : Use ESP32's WiFi client feature to connect and communicate with a remote IP.
|
||||
Auther : www.freenove.com
|
||||
Modification: 2022/10/31
|
||||
**********************************************************************/
|
||||
#include <WiFi.h>
|
||||
|
||||
const char *ssid_Router = "********"; //Enter the router name
|
||||
const char *password_Router = "********"; //Enter the router password
|
||||
#define REMOTE_IP "********" //input the remote server which is you want to connect
|
||||
#define REMOTE_PORT 8888 //input the remote port which is the remote provide
|
||||
WiFiClient client;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(10);
|
||||
|
||||
WiFi.begin(ssid_Router, password_Router);
|
||||
Serial.print("\nWaiting for WiFi... ");
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.print(".");
|
||||
delay(500);
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
delay(500);
|
||||
|
||||
Serial.print("Connecting to ");
|
||||
Serial.println(REMOTE_IP);
|
||||
|
||||
while (!client.connect(REMOTE_IP, REMOTE_PORT)) {
|
||||
Serial.println("Connection failed.");
|
||||
Serial.println("Waiting a moment before retrying...");
|
||||
}
|
||||
Serial.println("Connected");
|
||||
client.print("Hello\n");
|
||||
client.print("This is my IP.\n");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (client.available() > 0) {
|
||||
delay(20);
|
||||
//read back one line from the server
|
||||
String line = client.readString();
|
||||
Serial.println(REMOTE_IP + String(":") + line);
|
||||
}
|
||||
if (Serial.available() > 0) {
|
||||
delay(20);
|
||||
String line = Serial.readString();
|
||||
client.print(line);
|
||||
}
|
||||
if (client.connected () == 0) {
|
||||
client.stop();
|
||||
WiFi.disconnect();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Sketch WiFi Client and Server
|
||||
* Author Zhentao Lin @ Freenove (http://www.freenove.com)
|
||||
* Date 2020/7/11
|
||||
******************************************************************************
|
||||
* Brief
|
||||
* This sketch is used to control a 2D ellipse through communicate to an
|
||||
* ESP32 board or other micro controller.
|
||||
* It will automatically detect and connect to a device (serial port) which
|
||||
* use the same trans format.
|
||||
******************************************************************************
|
||||
* Copyright
|
||||
* Copyright © Freenove (http://www.freenove.com)
|
||||
* License
|
||||
* Creative Commons Attribution ShareAlike 3.0
|
||||
* (http://creativecommons.org/licenses/by-sa/3.0/legalcode)
|
||||
******************************************************************************
|
||||
*/
|
||||
import controlP5.*;
|
||||
import processing.net.*;
|
||||
|
||||
ControlP5 cp5;
|
||||
//Println console;
|
||||
Server myServer;
|
||||
Client myClient;
|
||||
int dataIn=0;
|
||||
int radioFlag1=0;
|
||||
int radioFlag2=0;
|
||||
int send_flag=1;
|
||||
|
||||
void setup() {
|
||||
size(600,400);
|
||||
smooth();
|
||||
noStroke();
|
||||
cp5 = new ControlP5(this);
|
||||
cp5.addTab("default")
|
||||
.activateEvent(true)
|
||||
.setHeight(30)
|
||||
.setWidth(100)
|
||||
.setLabel("TCP Server")
|
||||
.setId(1)
|
||||
;
|
||||
cp5.getTab("TCP Client")
|
||||
.activateEvent(true)
|
||||
.setHeight(30)
|
||||
.setWidth(100)
|
||||
.setId(2)
|
||||
;
|
||||
|
||||
cp5.addTextfield("Local IP")
|
||||
.setPosition(20,40)
|
||||
.setSize(160,40)
|
||||
.setFont(createFont("微软雅黑 Light",20))
|
||||
.setColor(color(255,255,0))
|
||||
.setColorLabel(color(0))
|
||||
.setColorBackground(color(100,255))
|
||||
.moveTo("default")
|
||||
;
|
||||
cp5.addTextfield("Local PORT")
|
||||
.setPosition(20,120)
|
||||
.setSize(160,40)
|
||||
.setFont(createFont("微软雅黑 Light",20))
|
||||
.setColor(color(255,255,0))
|
||||
.setColorLabel(color(0))
|
||||
.setColorBackground(color(100,255))
|
||||
.setText("8888")
|
||||
.moveTo("default")
|
||||
;
|
||||
cp5.addRadioButton("connect1")
|
||||
.setPosition(20,200)
|
||||
.setSize(100,25)
|
||||
.addItem("Listening", 1)
|
||||
.setColorLabel(color(0))
|
||||
.moveTo("default")
|
||||
;
|
||||
|
||||
cp5.addTextfield("Remote IP")
|
||||
.setPosition(20,40)
|
||||
.setSize(160,40)
|
||||
.setFont(createFont("微软雅黑 Light",20))
|
||||
.setColor(color(255,255,0))
|
||||
.setColorLabel(color(0))
|
||||
.setColorBackground(color(100,255))
|
||||
.setText("192.168.1.xxx")
|
||||
.moveTo("TCP Client")
|
||||
;
|
||||
cp5.addTextfield("Remote PORT")
|
||||
.setPosition(20,120)
|
||||
.setSize(160,40)
|
||||
.setFont(createFont("微软雅黑 Light",20))
|
||||
.setColor(color(255,255,0))
|
||||
.setColorLabel(color(0))
|
||||
.setColorBackground(color(100,255))
|
||||
.setText("80")
|
||||
.moveTo("TCP Client")
|
||||
;
|
||||
cp5.addRadioButton("connect2")
|
||||
.setPosition(20,200)
|
||||
.setSize(100,25)
|
||||
.addItem("connect Server",1)
|
||||
.setColorLabel(color(0))
|
||||
.moveTo("TCP Client")
|
||||
;
|
||||
|
||||
cp5.addTextarea("recvData")
|
||||
.setPosition(200,40)
|
||||
.setSize(350,150)
|
||||
.setFont(createFont("微软雅黑 Light",20))
|
||||
.setColor(color(255,255,0))
|
||||
.setColorBackground(color(100,255))
|
||||
.scroll(15)
|
||||
.setColorForeground(color(0,100))
|
||||
.moveTo("global")
|
||||
;
|
||||
cp5.addTextfield("sendData")
|
||||
.setPosition(200,230)
|
||||
.setSize(350,80)
|
||||
.setFont(createFont("微软雅黑 Light",20))
|
||||
.setColor(color(255,255,0))
|
||||
.setLabel("")
|
||||
.setFocus(true)
|
||||
.setColorBackground(color(100,255))
|
||||
.setColorForeground(color(0,100))
|
||||
.moveTo("global")
|
||||
;
|
||||
cp5.addButton("clearRecv")
|
||||
.setValue(0)
|
||||
.setPosition(200,200)
|
||||
.setSize(100,20)
|
||||
.setColorLabel(color(255,100))
|
||||
.moveTo("global")
|
||||
;
|
||||
cp5.addButton("clearSend")
|
||||
.setValue(0)
|
||||
.setPosition(200,320)
|
||||
.setSize(100,20)
|
||||
.setColorLabel(color(255,100))
|
||||
.moveTo("global")
|
||||
;
|
||||
cp5.addButton("Send")
|
||||
.setValue(0)
|
||||
.setPosition(450,320)
|
||||
.setSize(100,20)
|
||||
.plugTo(this,"send_Textfield_SendData")
|
||||
.setColorLabel(color(255,100))
|
||||
.moveTo("global")
|
||||
;
|
||||
cp5.get(Textfield.class,"Local IP").setText(Server.ip());
|
||||
}
|
||||
|
||||
void draw(){
|
||||
background(220);
|
||||
if(radioFlag1==1){
|
||||
Client thisClient = myServer.available();
|
||||
if (thisClient !=null) {
|
||||
String whatClientSaid = thisClient.readString();
|
||||
if (whatClientSaid != null) {
|
||||
cp5.get(Textarea.class,"recvData").append(thisClient.ip()+": ");
|
||||
cp5.get(Textarea.class,"recvData").append(whatClientSaid+"\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// myServer.active()
|
||||
if(radioFlag2==1){
|
||||
if (myClient.available() > 0) {
|
||||
String whatClientSaid = myClient.readString();
|
||||
if (whatClientSaid != null) {
|
||||
cp5.get(Textarea.class,"recvData").append(cp5.get(Textfield.class,"Remote IP").getText()+": ");
|
||||
cp5.get(Textarea.class,"recvData").append(whatClientSaid+"\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void controlEvent(ControlEvent theControlEvent) {
|
||||
if (theControlEvent.isTab()) {
|
||||
if(theControlEvent.getTab().getId()==1){
|
||||
cp5.get(Textarea.class,"recvData").clear();
|
||||
cp5.get(Textfield.class,"sendData").clear();
|
||||
send_flag=1;
|
||||
}
|
||||
else if(theControlEvent.getTab().getId()==2){
|
||||
cp5.get(Textarea.class,"recvData").clear();
|
||||
cp5.get(Textfield.class,"sendData").clear();
|
||||
send_flag=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void connect1(int a) {
|
||||
println("a radio Button event: "+a);
|
||||
radioFlag1=a;
|
||||
if(radioFlag1==1){
|
||||
String port_buffer = cp5.get(Textfield.class,"Local PORT").getText();
|
||||
int port = int(port_buffer);
|
||||
myServer = new Server(this,port);
|
||||
println(Server.ip());
|
||||
cp5.get(Textfield.class,"Local IP").setText(Server.ip());
|
||||
println(port);
|
||||
}
|
||||
else
|
||||
myServer.stop();
|
||||
}
|
||||
void connect2(int a) {
|
||||
println("a radio Button event: "+a);
|
||||
radioFlag2=a;
|
||||
if(radioFlag2==1){
|
||||
String port_buffer = cp5.get(Textfield.class,"Remote PORT").getText();
|
||||
String IP_buffer = cp5.get(Textfield.class,"Remote IP").getText();
|
||||
int port = int(port_buffer);
|
||||
if(IP_buffer.compareTo("192.168.1.xxx")==0){
|
||||
println("connect error!");
|
||||
}
|
||||
else{
|
||||
myClient = new Client(this,IP_buffer,port);
|
||||
println("connect success!");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
myClient.stop();
|
||||
}
|
||||
void clearRecv(){
|
||||
cp5.get(Textarea.class,"recvData").clear();
|
||||
}
|
||||
void clearSend(){
|
||||
cp5.get(Textfield.class,"sendData").clear();
|
||||
}
|
||||
void send_Textfield_SendData(){
|
||||
if(send_flag==1){
|
||||
myServer.write(cp5.get(Textfield.class,"sendData").getText());
|
||||
cp5.get(Textfield.class,"sendData").clear();
|
||||
}
|
||||
else if(send_flag==2){
|
||||
myClient.write(cp5.get(Textfield.class,"sendData").getText());
|
||||
cp5.get(Textfield.class,"sendData").clear();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/**********************************************************************
|
||||
Filename : WiFi Server
|
||||
Description : Use ESP32's WiFi server feature to wait for other WiFi devices to connect.
|
||||
And communicate with them once a connection has been established.
|
||||
Auther : www.freenove.com
|
||||
Modification: 2024/07/01
|
||||
**********************************************************************/
|
||||
#include <WiFi.h>
|
||||
|
||||
#define port 80
|
||||
const char *ssid_Router = "********"; //input your wifi name
|
||||
const char *password_Router = "********"; //input your wifi passwords
|
||||
WiFiServer server(port);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.printf("\nConnecting to ");
|
||||
Serial.println(ssid_Router);
|
||||
WiFi.disconnect();
|
||||
WiFi.begin(ssid_Router, password_Router);
|
||||
delay(1000);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected.");
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.printf("IP port: %d\n",port);
|
||||
server.begin(port);
|
||||
WiFi.setAutoReconnect(true);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
WiFiClient client = server.accept(); // listen for incoming clients
|
||||
if (client) { // if you get a client,
|
||||
Serial.println("Client connected.");
|
||||
while (client.connected()) { // loop while the client's connected
|
||||
if (client.available()) { // if there's bytes to read from the client,
|
||||
Serial.println(client.readStringUntil('\n')); // print it out the serial monitor
|
||||
while(client.read()>0); // clear the wifi receive area cache
|
||||
}
|
||||
if(Serial.available()){ // if there's bytes to read from the serial monitor,
|
||||
client.print(Serial.readStringUntil('\n')); // print it out the client.
|
||||
while(Serial.read()>0); // clear the wifi receive area cache
|
||||
}
|
||||
}
|
||||
client.stop(); // stop the client connecting.
|
||||
Serial.println("Client Disconnected.");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Sketch WiFi Client and Server
|
||||
* Author Zhentao Lin @ Freenove (http://www.freenove.com)
|
||||
* Date 2020/7/11
|
||||
******************************************************************************
|
||||
* Brief
|
||||
* This sketch is used to control a 2D ellipse through communicate to an
|
||||
* ESP32 board or other micro controller.
|
||||
* It will automatically detect and connect to a device (serial port) which
|
||||
* use the same trans format.
|
||||
******************************************************************************
|
||||
* Copyright
|
||||
* Copyright © Freenove (http://www.freenove.com)
|
||||
* License
|
||||
* Creative Commons Attribution ShareAlike 3.0
|
||||
* (http://creativecommons.org/licenses/by-sa/3.0/legalcode)
|
||||
******************************************************************************
|
||||
*/
|
||||
import controlP5.*;
|
||||
import processing.net.*;
|
||||
|
||||
ControlP5 cp5;
|
||||
//Println console;
|
||||
Server myServer;
|
||||
Client myClient;
|
||||
int dataIn=0;
|
||||
int radioFlag1=0;
|
||||
int radioFlag2=0;
|
||||
int send_flag=1;
|
||||
|
||||
void setup() {
|
||||
size(600,400);
|
||||
smooth();
|
||||
noStroke();
|
||||
cp5 = new ControlP5(this);
|
||||
cp5.addTab("default")
|
||||
.activateEvent(true)
|
||||
.setHeight(30)
|
||||
.setWidth(100)
|
||||
.setLabel("TCP Server")
|
||||
.setId(1)
|
||||
;
|
||||
cp5.getTab("TCP Client")
|
||||
.activateEvent(true)
|
||||
.setHeight(30)
|
||||
.setWidth(100)
|
||||
.setId(2)
|
||||
;
|
||||
|
||||
cp5.addTextfield("Local IP")
|
||||
.setPosition(20,40)
|
||||
.setSize(160,40)
|
||||
.setFont(createFont("微软雅黑 Light",20))
|
||||
.setColor(color(255,255,0))
|
||||
.setColorLabel(color(0))
|
||||
.setColorBackground(color(100,255))
|
||||
.moveTo("default")
|
||||
;
|
||||
cp5.addTextfield("Local PORT")
|
||||
.setPosition(20,120)
|
||||
.setSize(160,40)
|
||||
.setFont(createFont("微软雅黑 Light",20))
|
||||
.setColor(color(255,255,0))
|
||||
.setColorLabel(color(0))
|
||||
.setColorBackground(color(100,255))
|
||||
.setText("8888")
|
||||
.moveTo("default")
|
||||
;
|
||||
cp5.addRadioButton("connect1")
|
||||
.setPosition(20,200)
|
||||
.setSize(100,25)
|
||||
.addItem("Listening", 1)
|
||||
.setColorLabel(color(0))
|
||||
.moveTo("default")
|
||||
;
|
||||
|
||||
cp5.addTextfield("Remote IP")
|
||||
.setPosition(20,40)
|
||||
.setSize(160,40)
|
||||
.setFont(createFont("微软雅黑 Light",20))
|
||||
.setColor(color(255,255,0))
|
||||
.setColorLabel(color(0))
|
||||
.setColorBackground(color(100,255))
|
||||
.setText("192.168.1.xxx")
|
||||
.moveTo("TCP Client")
|
||||
;
|
||||
cp5.addTextfield("Remote PORT")
|
||||
.setPosition(20,120)
|
||||
.setSize(160,40)
|
||||
.setFont(createFont("微软雅黑 Light",20))
|
||||
.setColor(color(255,255,0))
|
||||
.setColorLabel(color(0))
|
||||
.setColorBackground(color(100,255))
|
||||
.setText("80")
|
||||
.moveTo("TCP Client")
|
||||
;
|
||||
cp5.addRadioButton("connect2")
|
||||
.setPosition(20,200)
|
||||
.setSize(100,25)
|
||||
.addItem("connect Server",1)
|
||||
.setColorLabel(color(0))
|
||||
.moveTo("TCP Client")
|
||||
;
|
||||
|
||||
cp5.addTextarea("recvData")
|
||||
.setPosition(200,40)
|
||||
.setSize(350,150)
|
||||
.setFont(createFont("微软雅黑 Light",20))
|
||||
.setColor(color(255,255,0))
|
||||
.setColorBackground(color(100,255))
|
||||
.scroll(15)
|
||||
.setColorForeground(color(0,100))
|
||||
.moveTo("global")
|
||||
;
|
||||
cp5.addTextfield("sendData")
|
||||
.setPosition(200,230)
|
||||
.setSize(350,80)
|
||||
.setFont(createFont("微软雅黑 Light",20))
|
||||
.setColor(color(255,255,0))
|
||||
.setLabel("")
|
||||
.setFocus(true)
|
||||
.setColorBackground(color(100,255))
|
||||
.setColorForeground(color(0,100))
|
||||
.moveTo("global")
|
||||
;
|
||||
cp5.addButton("clearRecv")
|
||||
.setValue(0)
|
||||
.setPosition(200,200)
|
||||
.setSize(100,20)
|
||||
.setColorLabel(color(255,100))
|
||||
.moveTo("global")
|
||||
;
|
||||
cp5.addButton("clearSend")
|
||||
.setValue(0)
|
||||
.setPosition(200,320)
|
||||
.setSize(100,20)
|
||||
.setColorLabel(color(255,100))
|
||||
.moveTo("global")
|
||||
;
|
||||
cp5.addButton("Send")
|
||||
.setValue(0)
|
||||
.setPosition(450,320)
|
||||
.setSize(100,20)
|
||||
.plugTo(this,"send_Textfield_SendData")
|
||||
.setColorLabel(color(255,100))
|
||||
.moveTo("global")
|
||||
;
|
||||
cp5.get(Textfield.class,"Local IP").setText(Server.ip());
|
||||
}
|
||||
|
||||
void draw(){
|
||||
background(220);
|
||||
if(radioFlag1==1){
|
||||
Client thisClient = myServer.available();
|
||||
if (thisClient !=null) {
|
||||
String whatClientSaid = thisClient.readString();
|
||||
if (whatClientSaid != null) {
|
||||
cp5.get(Textarea.class,"recvData").append(thisClient.ip()+": ");
|
||||
cp5.get(Textarea.class,"recvData").append(whatClientSaid+"\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// myServer.active()
|
||||
if(radioFlag2==1){
|
||||
if (myClient.available() > 0) {
|
||||
String whatClientSaid = myClient.readString();
|
||||
if (whatClientSaid != null) {
|
||||
cp5.get(Textarea.class,"recvData").append(cp5.get(Textfield.class,"Remote IP").getText()+": ");
|
||||
cp5.get(Textarea.class,"recvData").append(whatClientSaid+"\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void controlEvent(ControlEvent theControlEvent) {
|
||||
if (theControlEvent.isTab()) {
|
||||
if(theControlEvent.getTab().getId()==1){
|
||||
cp5.get(Textarea.class,"recvData").clear();
|
||||
cp5.get(Textfield.class,"sendData").clear();
|
||||
send_flag=1;
|
||||
}
|
||||
else if(theControlEvent.getTab().getId()==2){
|
||||
cp5.get(Textarea.class,"recvData").clear();
|
||||
cp5.get(Textfield.class,"sendData").clear();
|
||||
send_flag=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void connect1(int a) {
|
||||
println("a radio Button event: "+a);
|
||||
radioFlag1=a;
|
||||
if(radioFlag1==1){
|
||||
String port_buffer = cp5.get(Textfield.class,"Local PORT").getText();
|
||||
int port = int(port_buffer);
|
||||
myServer = new Server(this,port);
|
||||
println(Server.ip());
|
||||
cp5.get(Textfield.class,"Local IP").setText(Server.ip());
|
||||
println(port);
|
||||
}
|
||||
else
|
||||
myServer.stop();
|
||||
}
|
||||
void connect2(int a) {
|
||||
println("a radio Button event: "+a);
|
||||
radioFlag2=a;
|
||||
if(radioFlag2==1){
|
||||
String port_buffer = cp5.get(Textfield.class,"Remote PORT").getText();
|
||||
String IP_buffer = cp5.get(Textfield.class,"Remote IP").getText();
|
||||
int port = int(port_buffer);
|
||||
if(IP_buffer.compareTo("192.168.1.xxx")==0){
|
||||
println("connect error!");
|
||||
}
|
||||
else{
|
||||
myClient = new Client(this,IP_buffer,port);
|
||||
println("connect success!");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
myClient.stop();
|
||||
}
|
||||
void clearRecv(){
|
||||
cp5.get(Textarea.class,"recvData").clear();
|
||||
}
|
||||
void clearSend(){
|
||||
cp5.get(Textfield.class,"sendData").clear();
|
||||
}
|
||||
void send_Textfield_SendData(){
|
||||
if(send_flag==1){
|
||||
myServer.write(cp5.get(Textfield.class,"sendData").getText());
|
||||
cp5.get(Textfield.class,"sendData").clear();
|
||||
}
|
||||
else if(send_flag==2){
|
||||
myClient.write(cp5.get(Textfield.class,"sendData").getText());
|
||||
cp5.get(Textfield.class,"sendData").clear();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/**********************************************************************
|
||||
Filename : Camera Web Server
|
||||
Description : The camera images captured by the ESP32S3 are displayed on the web page.
|
||||
Auther : www.freenove.com
|
||||
Modification: 2024/07/01
|
||||
**********************************************************************/
|
||||
#include "esp_camera.h"
|
||||
#include <WiFi.h>
|
||||
|
||||
// ===================
|
||||
// Select camera model
|
||||
// ===================
|
||||
//#define CAMERA_MODEL_WROVER_KIT // Has PSRAM
|
||||
//#define CAMERA_MODEL_ESP_EYE // Has PSRAM
|
||||
#define CAMERA_MODEL_ESP32S3_EYE // Has PSRAM
|
||||
//#define CAMERA_MODEL_M5STACK_PSRAM // Has PSRAM
|
||||
//#define CAMERA_MODEL_M5STACK_V2_PSRAM // M5Camera version B Has PSRAM
|
||||
//#define CAMERA_MODEL_M5STACK_WIDE // Has PSRAM
|
||||
//#define CAMERA_MODEL_M5STACK_ESP32CAM // No PSRAM
|
||||
//#define CAMERA_MODEL_M5STACK_UNITCAM // No PSRAM
|
||||
//#define CAMERA_MODEL_AI_THINKER // Has PSRAM
|
||||
//#define CAMERA_MODEL_TTGO_T_JOURNAL // No PSRAM
|
||||
// ** Espressif Internal Boards **
|
||||
//#define CAMERA_MODEL_ESP32_CAM_BOARD
|
||||
//#define CAMERA_MODEL_ESP32S2_CAM_BOARD
|
||||
//#define CAMERA_MODEL_ESP32S3_CAM_LCD
|
||||
|
||||
#include "camera_pins.h"
|
||||
|
||||
// ===========================
|
||||
// Enter your WiFi credentials
|
||||
// ===========================
|
||||
const char* ssid = "********";
|
||||
const char* password = "********";
|
||||
|
||||
void startCameraServer();
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(true);
|
||||
Serial.println();
|
||||
|
||||
camera_config_t config;
|
||||
config.ledc_channel = LEDC_CHANNEL_0;
|
||||
config.ledc_timer = LEDC_TIMER_0;
|
||||
config.pin_d0 = Y2_GPIO_NUM;
|
||||
config.pin_d1 = Y3_GPIO_NUM;
|
||||
config.pin_d2 = Y4_GPIO_NUM;
|
||||
config.pin_d3 = Y5_GPIO_NUM;
|
||||
config.pin_d4 = Y6_GPIO_NUM;
|
||||
config.pin_d5 = Y7_GPIO_NUM;
|
||||
config.pin_d6 = Y8_GPIO_NUM;
|
||||
config.pin_d7 = Y9_GPIO_NUM;
|
||||
config.pin_xclk = XCLK_GPIO_NUM;
|
||||
config.pin_pclk = PCLK_GPIO_NUM;
|
||||
config.pin_vsync = VSYNC_GPIO_NUM;
|
||||
config.pin_href = HREF_GPIO_NUM;
|
||||
config.pin_sccb_sda = SIOD_GPIO_NUM;
|
||||
config.pin_sccb_scl = SIOC_GPIO_NUM;
|
||||
config.pin_pwdn = PWDN_GPIO_NUM;
|
||||
config.pin_reset = RESET_GPIO_NUM;
|
||||
config.xclk_freq_hz = 20000000;
|
||||
config.frame_size = FRAMESIZE_UXGA;
|
||||
config.pixel_format = PIXFORMAT_JPEG; // for streaming
|
||||
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
|
||||
config.fb_location = CAMERA_FB_IN_PSRAM;
|
||||
config.jpeg_quality = 12;
|
||||
config.fb_count = 1;
|
||||
|
||||
// if PSRAM IC present, init with UXGA resolution and higher JPEG quality
|
||||
// for larger pre-allocated frame buffer.
|
||||
if(psramFound()){
|
||||
config.jpeg_quality = 10;
|
||||
config.fb_count = 2;
|
||||
config.grab_mode = CAMERA_GRAB_LATEST;
|
||||
} else {
|
||||
// Limit the frame size when PSRAM is not available
|
||||
config.frame_size = FRAMESIZE_SVGA;
|
||||
config.fb_location = CAMERA_FB_IN_DRAM;
|
||||
}
|
||||
|
||||
// camera init
|
||||
esp_err_t err = esp_camera_init(&config);
|
||||
if (err != ESP_OK) {
|
||||
Serial.printf("Camera init failed with error 0x%x", err);
|
||||
return;
|
||||
}
|
||||
|
||||
sensor_t * s = esp_camera_sensor_get();
|
||||
// initial sensors are flipped vertically and colors are a bit saturated
|
||||
s->set_vflip(s, 1); // flip it back
|
||||
s->set_brightness(s, 1); // up the brightness just a bit
|
||||
s->set_saturation(s, 0); // lower the saturation
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
WiFi.setSleep(false);
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
while (WiFi.STA.hasIP() != true) {
|
||||
Serial.print(".");
|
||||
delay(500);
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
|
||||
startCameraServer();
|
||||
|
||||
Serial.print("Camera Ready! Use 'http://");
|
||||
Serial.print(WiFi.localIP());
|
||||
Serial.println("' to connect");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Do nothing. Everything is done in another task by the web server
|
||||
delay(10000);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,273 @@
|
|||
|
||||
#if defined(CAMERA_MODEL_WROVER_KIT)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 21
|
||||
#define SIOD_GPIO_NUM 26
|
||||
#define SIOC_GPIO_NUM 27
|
||||
|
||||
#define Y9_GPIO_NUM 35
|
||||
#define Y8_GPIO_NUM 34
|
||||
#define Y7_GPIO_NUM 39
|
||||
#define Y6_GPIO_NUM 36
|
||||
#define Y5_GPIO_NUM 19
|
||||
#define Y4_GPIO_NUM 18
|
||||
#define Y3_GPIO_NUM 5
|
||||
#define Y2_GPIO_NUM 4
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 23
|
||||
#define PCLK_GPIO_NUM 22
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP_EYE)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 4
|
||||
#define SIOD_GPIO_NUM 18
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 36
|
||||
#define Y8_GPIO_NUM 37
|
||||
#define Y7_GPIO_NUM 38
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 35
|
||||
#define Y4_GPIO_NUM 14
|
||||
#define Y3_GPIO_NUM 13
|
||||
#define Y2_GPIO_NUM 34
|
||||
#define VSYNC_GPIO_NUM 5
|
||||
#define HREF_GPIO_NUM 27
|
||||
#define PCLK_GPIO_NUM 25
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_V2_PSRAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 22
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_WIDE)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 22
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_ESP32CAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 17
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_UNITCAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_AI_THINKER)
|
||||
#define PWDN_GPIO_NUM 32
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 0
|
||||
#define SIOD_GPIO_NUM 26
|
||||
#define SIOC_GPIO_NUM 27
|
||||
|
||||
#define Y9_GPIO_NUM 35
|
||||
#define Y8_GPIO_NUM 34
|
||||
#define Y7_GPIO_NUM 39
|
||||
#define Y6_GPIO_NUM 36
|
||||
#define Y5_GPIO_NUM 21
|
||||
#define Y4_GPIO_NUM 19
|
||||
#define Y3_GPIO_NUM 18
|
||||
#define Y2_GPIO_NUM 5
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 23
|
||||
#define PCLK_GPIO_NUM 22
|
||||
|
||||
#elif defined(CAMERA_MODEL_TTGO_T_JOURNAL)
|
||||
#define PWDN_GPIO_NUM 0
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 17
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32_CAM_BOARD)
|
||||
// The 18 pin header on the board has Y5 and Y3 swapped
|
||||
#define USE_BOARD_HEADER 0
|
||||
#define PWDN_GPIO_NUM 32
|
||||
#define RESET_GPIO_NUM 33
|
||||
#define XCLK_GPIO_NUM 4
|
||||
#define SIOD_GPIO_NUM 18
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 36
|
||||
#define Y8_GPIO_NUM 19
|
||||
#define Y7_GPIO_NUM 21
|
||||
#define Y6_GPIO_NUM 39
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y5_GPIO_NUM 13
|
||||
#else
|
||||
#define Y5_GPIO_NUM 35
|
||||
#endif
|
||||
#define Y4_GPIO_NUM 14
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y3_GPIO_NUM 35
|
||||
#else
|
||||
#define Y3_GPIO_NUM 13
|
||||
#endif
|
||||
#define Y2_GPIO_NUM 34
|
||||
#define VSYNC_GPIO_NUM 5
|
||||
#define HREF_GPIO_NUM 27
|
||||
#define PCLK_GPIO_NUM 25
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32S3_CAM_LCD)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 40
|
||||
#define SIOD_GPIO_NUM 17
|
||||
#define SIOC_GPIO_NUM 18
|
||||
|
||||
#define Y9_GPIO_NUM 39
|
||||
#define Y8_GPIO_NUM 41
|
||||
#define Y7_GPIO_NUM 42
|
||||
#define Y6_GPIO_NUM 12
|
||||
#define Y5_GPIO_NUM 3
|
||||
#define Y4_GPIO_NUM 14
|
||||
#define Y3_GPIO_NUM 47
|
||||
#define Y2_GPIO_NUM 13
|
||||
#define VSYNC_GPIO_NUM 21
|
||||
#define HREF_GPIO_NUM 38
|
||||
#define PCLK_GPIO_NUM 11
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32S2_CAM_BOARD)
|
||||
// The 18 pin header on the board has Y5 and Y3 swapped
|
||||
#define USE_BOARD_HEADER 0
|
||||
#define PWDN_GPIO_NUM 1
|
||||
#define RESET_GPIO_NUM 2
|
||||
#define XCLK_GPIO_NUM 42
|
||||
#define SIOD_GPIO_NUM 41
|
||||
#define SIOC_GPIO_NUM 18
|
||||
|
||||
#define Y9_GPIO_NUM 16
|
||||
#define Y8_GPIO_NUM 39
|
||||
#define Y7_GPIO_NUM 40
|
||||
#define Y6_GPIO_NUM 15
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y5_GPIO_NUM 12
|
||||
#else
|
||||
#define Y5_GPIO_NUM 13
|
||||
#endif
|
||||
#define Y4_GPIO_NUM 5
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y3_GPIO_NUM 13
|
||||
#else
|
||||
#define Y3_GPIO_NUM 12
|
||||
#endif
|
||||
#define Y2_GPIO_NUM 14
|
||||
#define VSYNC_GPIO_NUM 38
|
||||
#define HREF_GPIO_NUM 4
|
||||
#define PCLK_GPIO_NUM 3
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32S3_EYE)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 15
|
||||
#define SIOD_GPIO_NUM 4
|
||||
#define SIOC_GPIO_NUM 5
|
||||
|
||||
#define Y2_GPIO_NUM 11
|
||||
#define Y3_GPIO_NUM 9
|
||||
#define Y4_GPIO_NUM 8
|
||||
#define Y5_GPIO_NUM 10
|
||||
#define Y6_GPIO_NUM 12
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y8_GPIO_NUM 17
|
||||
#define Y9_GPIO_NUM 16
|
||||
|
||||
#define VSYNC_GPIO_NUM 6
|
||||
#define HREF_GPIO_NUM 7
|
||||
#define PCLK_GPIO_NUM 13
|
||||
|
||||
#else
|
||||
#error "Camera model not selected"
|
||||
#endif
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/**********************************************************************
|
||||
Filename : Video Web Server
|
||||
Description : The camera images captured by the ESP32S3 are displayed on the web page.
|
||||
Auther : www.freenove.com
|
||||
Modification: 2022/11/01
|
||||
**********************************************************************/
|
||||
#include "esp_camera.h"
|
||||
#include <WiFi.h>
|
||||
#include "sd_read_write.h"
|
||||
|
||||
// Select camera model
|
||||
#define CAMERA_MODEL_ESP32S3_EYE // Has PSRAM
|
||||
|
||||
#include "camera_pins.h"
|
||||
|
||||
const char* ssid = "********"; //input your wifi name
|
||||
const char* password = "********"; //input your wifi passwords
|
||||
|
||||
void cameraInit(void);
|
||||
void startCameraServer();
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(true);
|
||||
Serial.println();
|
||||
|
||||
cameraInit();
|
||||
sdmmcInit();
|
||||
removeDir(SD_MMC, "/video");
|
||||
createDir(SD_MMC, "/video");
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
|
||||
startCameraServer();
|
||||
|
||||
Serial.print("Camera Ready! Use 'http://");
|
||||
Serial.print(WiFi.localIP());
|
||||
Serial.println("' to connect");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// put your main code here, to run repeatedly:
|
||||
delay(10000);
|
||||
}
|
||||
|
||||
void cameraInit(void){
|
||||
camera_config_t config;
|
||||
config.ledc_channel = LEDC_CHANNEL_0;
|
||||
config.ledc_timer = LEDC_TIMER_0;
|
||||
config.pin_d0 = Y2_GPIO_NUM;
|
||||
config.pin_d1 = Y3_GPIO_NUM;
|
||||
config.pin_d2 = Y4_GPIO_NUM;
|
||||
config.pin_d3 = Y5_GPIO_NUM;
|
||||
config.pin_d4 = Y6_GPIO_NUM;
|
||||
config.pin_d5 = Y7_GPIO_NUM;
|
||||
config.pin_d6 = Y8_GPIO_NUM;
|
||||
config.pin_d7 = Y9_GPIO_NUM;
|
||||
config.pin_xclk = XCLK_GPIO_NUM;
|
||||
config.pin_pclk = PCLK_GPIO_NUM;
|
||||
config.pin_vsync = VSYNC_GPIO_NUM;
|
||||
config.pin_href = HREF_GPIO_NUM;
|
||||
config.pin_sccb_sda = SIOD_GPIO_NUM;
|
||||
config.pin_sccb_scl = SIOC_GPIO_NUM;
|
||||
config.pin_pwdn = PWDN_GPIO_NUM;
|
||||
config.pin_reset = RESET_GPIO_NUM;
|
||||
config.xclk_freq_hz = 20000000;
|
||||
config.frame_size = FRAMESIZE_UXGA;
|
||||
config.pixel_format = PIXFORMAT_JPEG; // for streaming
|
||||
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
|
||||
config.fb_location = CAMERA_FB_IN_PSRAM;
|
||||
config.jpeg_quality = 12;
|
||||
config.fb_count = 1;
|
||||
|
||||
// if PSRAM IC present, init with UXGA resolution and higher JPEG quality
|
||||
// for larger pre-allocated frame buffer.
|
||||
if(psramFound()){
|
||||
config.jpeg_quality = 10;
|
||||
config.fb_count = 2;
|
||||
config.grab_mode = CAMERA_GRAB_LATEST;
|
||||
} else {
|
||||
// Limit the frame size when PSRAM is not available
|
||||
config.frame_size = FRAMESIZE_SVGA;
|
||||
config.fb_location = CAMERA_FB_IN_DRAM;
|
||||
}
|
||||
|
||||
// camera init
|
||||
esp_err_t err = esp_camera_init(&config);
|
||||
if (err != ESP_OK) {
|
||||
Serial.printf("Camera init failed with error 0x%x", err);
|
||||
return;
|
||||
}
|
||||
|
||||
sensor_t * s = esp_camera_sensor_get();
|
||||
// initial sensors are flipped vertically and colors are a bit saturated
|
||||
s->set_vflip(s, 1); // flip it back
|
||||
s->set_brightness(s, 1); // up the brightness just a bit
|
||||
s->set_saturation(s, 0); // lower the saturation
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,335 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "esp_http_server.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_camera.h"
|
||||
#include "img_converters.h"
|
||||
#include "fb_gfx.h"
|
||||
#include "driver/ledc.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "sd_read_write.h"
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
|
||||
#include "esp32-hal-log.h"
|
||||
#define TAG ""
|
||||
#else
|
||||
#include "esp_log.h"
|
||||
static const char *TAG = "camera_httpd";
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
httpd_req_t *req;
|
||||
size_t len;
|
||||
} jpg_chunking_t;
|
||||
|
||||
#define PART_BOUNDARY "123456789000000000000987654321"
|
||||
static const char *_STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
|
||||
static const char *_STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
|
||||
static const char *_STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\nX-Timestamp: %d.%06d\r\n\r\n";
|
||||
|
||||
httpd_handle_t stream_httpd = NULL;
|
||||
httpd_handle_t camera_httpd = NULL;
|
||||
|
||||
static int button_state = 1;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t size; // number of values used for filtering
|
||||
size_t index; // current value index
|
||||
size_t count; // value count
|
||||
int sum;
|
||||
int *values; // array to be filled with values
|
||||
} ra_filter_t;
|
||||
|
||||
static ra_filter_t ra_filter;
|
||||
|
||||
static ra_filter_t *ra_filter_init(ra_filter_t *filter, size_t sample_size)
|
||||
{
|
||||
memset(filter, 0, sizeof(ra_filter_t));
|
||||
|
||||
filter->values = (int *)malloc(sample_size * sizeof(int));
|
||||
if (!filter->values)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
memset(filter->values, 0, sample_size * sizeof(int));
|
||||
|
||||
filter->size = sample_size;
|
||||
return filter;
|
||||
}
|
||||
|
||||
static int ra_filter_run(ra_filter_t *filter, int value)
|
||||
{
|
||||
if (!filter->values)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
filter->sum -= filter->values[filter->index];
|
||||
filter->values[filter->index] = value;
|
||||
filter->sum += filter->values[filter->index];
|
||||
filter->index++;
|
||||
filter->index = filter->index % filter->size;
|
||||
if (filter->count < filter->size)
|
||||
{
|
||||
filter->count++;
|
||||
}
|
||||
return filter->sum / filter->count;
|
||||
}
|
||||
|
||||
static esp_err_t stream_handler(httpd_req_t *req)
|
||||
{
|
||||
camera_fb_t *fb = NULL;
|
||||
struct timeval _timestamp;
|
||||
esp_err_t res = ESP_OK;
|
||||
size_t _jpg_buf_len = 0;
|
||||
uint8_t *_jpg_buf = NULL;
|
||||
char *part_buf[128];
|
||||
|
||||
static int64_t last_frame = 0;
|
||||
if (!last_frame)
|
||||
{
|
||||
last_frame = esp_timer_get_time();
|
||||
}
|
||||
|
||||
res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);
|
||||
if (res != ESP_OK)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_set_hdr(req, "X-Framerate", "60");
|
||||
|
||||
while (true)
|
||||
{
|
||||
fb = esp_camera_fb_get();
|
||||
if (!fb)
|
||||
{
|
||||
ESP_LOGE(TAG, "Camera capture failed");
|
||||
res = ESP_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
_timestamp.tv_sec = fb->timestamp.tv_sec;
|
||||
_timestamp.tv_usec = fb->timestamp.tv_usec;
|
||||
if (fb->format != PIXFORMAT_JPEG)
|
||||
{
|
||||
bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);
|
||||
esp_camera_fb_return(fb);
|
||||
fb = NULL;
|
||||
if (!jpeg_converted)
|
||||
{
|
||||
ESP_LOGE(TAG, "JPEG compression failed");
|
||||
res = ESP_FAIL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_jpg_buf_len = fb->len;
|
||||
_jpg_buf = fb->buf;
|
||||
}
|
||||
}
|
||||
if (res == ESP_OK)
|
||||
{
|
||||
res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
|
||||
}
|
||||
if (res == ESP_OK)
|
||||
{
|
||||
size_t hlen = snprintf((char *)part_buf, 128, _STREAM_PART, _jpg_buf_len, _timestamp.tv_sec, _timestamp.tv_usec);
|
||||
res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);
|
||||
}
|
||||
if (res == ESP_OK)
|
||||
{
|
||||
res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);
|
||||
}
|
||||
if (fb)
|
||||
{
|
||||
esp_camera_fb_return(fb);
|
||||
fb = NULL;
|
||||
_jpg_buf = NULL;
|
||||
}
|
||||
else if (_jpg_buf)
|
||||
{
|
||||
free(_jpg_buf);
|
||||
_jpg_buf = NULL;
|
||||
}
|
||||
if (res != ESP_OK)
|
||||
{
|
||||
ESP_LOGI(TAG, "res != ESP_OK : %d , break!", res);
|
||||
break;
|
||||
}
|
||||
int64_t fr_end = esp_timer_get_time();
|
||||
|
||||
int64_t frame_time = fr_end - last_frame;
|
||||
last_frame = fr_end;
|
||||
frame_time /= 1000;
|
||||
uint32_t avg_frame_time = ra_filter_run(&ra_filter, frame_time);
|
||||
/*
|
||||
ESP_LOGI(TAG, "MJPG: %uB %ums (%.1ffps), AVG: %ums (%.1ffps)",
|
||||
(uint32_t)(_jpg_buf_len),
|
||||
(uint32_t)frame_time, 1000.0 / (uint32_t)frame_time,
|
||||
avg_frame_time, 1000.0 / avg_frame_time);
|
||||
*/
|
||||
}
|
||||
ESP_LOGI(TAG, "Stream exit!");
|
||||
last_frame = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
static esp_err_t parse_get(httpd_req_t *req, char **obuf)
|
||||
{
|
||||
char *buf = NULL;
|
||||
size_t buf_len = 0;
|
||||
|
||||
buf_len = httpd_req_get_url_query_len(req) + 1;
|
||||
if (buf_len > 1)
|
||||
{
|
||||
buf = (char *)malloc(buf_len);
|
||||
if (!buf)
|
||||
{
|
||||
httpd_resp_send_500(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK)
|
||||
{
|
||||
*obuf = buf;
|
||||
return ESP_OK;
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
httpd_resp_send_404(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
const char index_web[]=R"rawliteral(
|
||||
<html>
|
||||
<head>
|
||||
<title>Video Streaming Demonstration</title>
|
||||
</head>
|
||||
<body>
|
||||
<p><h1>Video Streaming Demonstration</h1></p>
|
||||
<p><img id="stream" src="" style="transform:rotate(180deg)"/></p>
|
||||
<iframe width=0 height=0 frameborder=0 id="myiframe" name="myiframe"></iframe>
|
||||
<p><form action="/button" method="POST" target="myiframe"><input type="submit" value="Save it to SDcard"></form></p>
|
||||
</body>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function (event) {
|
||||
var baseHost = document.location.origin
|
||||
var streamUrl = baseHost + ':81'
|
||||
const view = document.getElementById('stream')
|
||||
view.src = `${streamUrl}/stream`
|
||||
});
|
||||
</script>
|
||||
</html>)rawliteral";
|
||||
|
||||
|
||||
static esp_err_t index_handler(httpd_req_t *req)
|
||||
{
|
||||
esp_err_t err;
|
||||
err = httpd_resp_set_type(req, "text/html");
|
||||
sensor_t *s = esp_camera_sensor_get();
|
||||
if (s != NULL)
|
||||
{
|
||||
err = httpd_resp_send(req, (const char *)index_web, sizeof(index_web));
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "Camera sensor not found");
|
||||
err = httpd_resp_send_500(req);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static esp_err_t button_handler(httpd_req_t *req)
|
||||
{
|
||||
esp_err_t err;
|
||||
camera_fb_t * fb = NULL;
|
||||
fb = esp_camera_fb_get();
|
||||
if (!fb)
|
||||
{
|
||||
ESP_LOGE(TAG, "Camera capture failed");
|
||||
err = ESP_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
String video = "/video";
|
||||
int jpgCount=readFileNum(SD_MMC, video.c_str());
|
||||
String path = video + "/" + String(jpgCount) +".jpg";
|
||||
writejpg(SD_MMC, path.c_str(), fb->buf, fb->len);
|
||||
esp_camera_fb_return(fb);
|
||||
fb = NULL;
|
||||
err=ESP_OK;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void startCameraServer()
|
||||
{
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
config.max_uri_handlers = 16;
|
||||
|
||||
httpd_uri_t index_uri = {
|
||||
.uri = "/",
|
||||
.method = HTTP_GET,
|
||||
.handler = index_handler,
|
||||
.user_ctx = NULL};
|
||||
|
||||
httpd_uri_t stream_uri = {
|
||||
.uri = "/stream",
|
||||
.method = HTTP_GET,
|
||||
.handler = stream_handler,
|
||||
.user_ctx = NULL};
|
||||
|
||||
httpd_uri_t button_uri = {
|
||||
.uri = "/button",
|
||||
.method = HTTP_POST,
|
||||
.handler = button_handler,
|
||||
.user_ctx = NULL};
|
||||
|
||||
ra_filter_init(&ra_filter, 20);
|
||||
|
||||
ESP_LOGI(TAG, "Starting web server on port: '%d'", config.server_port);
|
||||
if (httpd_start(&camera_httpd, &config) == ESP_OK)
|
||||
{
|
||||
httpd_register_uri_handler(camera_httpd, &index_uri);
|
||||
httpd_register_uri_handler(camera_httpd, &button_uri);
|
||||
// httpd_register_uri_handler(camera_httpd, &stream_uri);
|
||||
}
|
||||
|
||||
config.server_port += 1;
|
||||
config.ctrl_port += 1;
|
||||
ESP_LOGI(TAG, "Starting stream server on port: '%d'", config.server_port);
|
||||
if (httpd_start(&stream_httpd, &config) == ESP_OK)
|
||||
{
|
||||
httpd_register_uri_handler(stream_httpd, &stream_uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,273 @@
|
|||
|
||||
#if defined(CAMERA_MODEL_WROVER_KIT)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 21
|
||||
#define SIOD_GPIO_NUM 26
|
||||
#define SIOC_GPIO_NUM 27
|
||||
|
||||
#define Y9_GPIO_NUM 35
|
||||
#define Y8_GPIO_NUM 34
|
||||
#define Y7_GPIO_NUM 39
|
||||
#define Y6_GPIO_NUM 36
|
||||
#define Y5_GPIO_NUM 19
|
||||
#define Y4_GPIO_NUM 18
|
||||
#define Y3_GPIO_NUM 5
|
||||
#define Y2_GPIO_NUM 4
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 23
|
||||
#define PCLK_GPIO_NUM 22
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP_EYE)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 4
|
||||
#define SIOD_GPIO_NUM 18
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 36
|
||||
#define Y8_GPIO_NUM 37
|
||||
#define Y7_GPIO_NUM 38
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 35
|
||||
#define Y4_GPIO_NUM 14
|
||||
#define Y3_GPIO_NUM 13
|
||||
#define Y2_GPIO_NUM 34
|
||||
#define VSYNC_GPIO_NUM 5
|
||||
#define HREF_GPIO_NUM 27
|
||||
#define PCLK_GPIO_NUM 25
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_V2_PSRAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 22
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_WIDE)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 22
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_ESP32CAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 17
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_UNITCAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_AI_THINKER)
|
||||
#define PWDN_GPIO_NUM 32
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 0
|
||||
#define SIOD_GPIO_NUM 26
|
||||
#define SIOC_GPIO_NUM 27
|
||||
|
||||
#define Y9_GPIO_NUM 35
|
||||
#define Y8_GPIO_NUM 34
|
||||
#define Y7_GPIO_NUM 39
|
||||
#define Y6_GPIO_NUM 36
|
||||
#define Y5_GPIO_NUM 21
|
||||
#define Y4_GPIO_NUM 19
|
||||
#define Y3_GPIO_NUM 18
|
||||
#define Y2_GPIO_NUM 5
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 23
|
||||
#define PCLK_GPIO_NUM 22
|
||||
|
||||
#elif defined(CAMERA_MODEL_TTGO_T_JOURNAL)
|
||||
#define PWDN_GPIO_NUM 0
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 17
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32_CAM_BOARD)
|
||||
// The 18 pin header on the board has Y5 and Y3 swapped
|
||||
#define USE_BOARD_HEADER 0
|
||||
#define PWDN_GPIO_NUM 32
|
||||
#define RESET_GPIO_NUM 33
|
||||
#define XCLK_GPIO_NUM 4
|
||||
#define SIOD_GPIO_NUM 18
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 36
|
||||
#define Y8_GPIO_NUM 19
|
||||
#define Y7_GPIO_NUM 21
|
||||
#define Y6_GPIO_NUM 39
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y5_GPIO_NUM 13
|
||||
#else
|
||||
#define Y5_GPIO_NUM 35
|
||||
#endif
|
||||
#define Y4_GPIO_NUM 14
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y3_GPIO_NUM 35
|
||||
#else
|
||||
#define Y3_GPIO_NUM 13
|
||||
#endif
|
||||
#define Y2_GPIO_NUM 34
|
||||
#define VSYNC_GPIO_NUM 5
|
||||
#define HREF_GPIO_NUM 27
|
||||
#define PCLK_GPIO_NUM 25
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32S3_CAM_LCD)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 40
|
||||
#define SIOD_GPIO_NUM 17
|
||||
#define SIOC_GPIO_NUM 18
|
||||
|
||||
#define Y9_GPIO_NUM 39
|
||||
#define Y8_GPIO_NUM 41
|
||||
#define Y7_GPIO_NUM 42
|
||||
#define Y6_GPIO_NUM 12
|
||||
#define Y5_GPIO_NUM 3
|
||||
#define Y4_GPIO_NUM 14
|
||||
#define Y3_GPIO_NUM 47
|
||||
#define Y2_GPIO_NUM 13
|
||||
#define VSYNC_GPIO_NUM 21
|
||||
#define HREF_GPIO_NUM 38
|
||||
#define PCLK_GPIO_NUM 11
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32S2_CAM_BOARD)
|
||||
// The 18 pin header on the board has Y5 and Y3 swapped
|
||||
#define USE_BOARD_HEADER 0
|
||||
#define PWDN_GPIO_NUM 1
|
||||
#define RESET_GPIO_NUM 2
|
||||
#define XCLK_GPIO_NUM 42
|
||||
#define SIOD_GPIO_NUM 41
|
||||
#define SIOC_GPIO_NUM 18
|
||||
|
||||
#define Y9_GPIO_NUM 16
|
||||
#define Y8_GPIO_NUM 39
|
||||
#define Y7_GPIO_NUM 40
|
||||
#define Y6_GPIO_NUM 15
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y5_GPIO_NUM 12
|
||||
#else
|
||||
#define Y5_GPIO_NUM 13
|
||||
#endif
|
||||
#define Y4_GPIO_NUM 5
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y3_GPIO_NUM 13
|
||||
#else
|
||||
#define Y3_GPIO_NUM 12
|
||||
#endif
|
||||
#define Y2_GPIO_NUM 14
|
||||
#define VSYNC_GPIO_NUM 38
|
||||
#define HREF_GPIO_NUM 4
|
||||
#define PCLK_GPIO_NUM 3
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32S3_EYE)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 15
|
||||
#define SIOD_GPIO_NUM 4
|
||||
#define SIOC_GPIO_NUM 5
|
||||
|
||||
#define Y2_GPIO_NUM 11
|
||||
#define Y3_GPIO_NUM 9
|
||||
#define Y4_GPIO_NUM 8
|
||||
#define Y5_GPIO_NUM 10
|
||||
#define Y6_GPIO_NUM 12
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y8_GPIO_NUM 17
|
||||
#define Y9_GPIO_NUM 16
|
||||
|
||||
#define VSYNC_GPIO_NUM 6
|
||||
#define HREF_GPIO_NUM 7
|
||||
#define PCLK_GPIO_NUM 13
|
||||
|
||||
#else
|
||||
#error "Camera model not selected"
|
||||
#endif
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
#include "sd_read_write.h"
|
||||
|
||||
void sdmmcInit(void){
|
||||
SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
|
||||
if (!SD_MMC.begin("/sdcard", true, true, SDMMC_FREQ_DEFAULT, 5)) {
|
||||
Serial.println("Card Mount Failed");
|
||||
return;
|
||||
}
|
||||
uint8_t cardType = SD_MMC.cardType();
|
||||
if(cardType == CARD_NONE){
|
||||
Serial.println("No SD_MMC card attached");
|
||||
return;
|
||||
}
|
||||
Serial.print("SD_MMC Card Type: ");
|
||||
if(cardType == CARD_MMC){
|
||||
Serial.println("MMC");
|
||||
} else if(cardType == CARD_SD){
|
||||
Serial.println("SDSC");
|
||||
} else if(cardType == CARD_SDHC){
|
||||
Serial.println("SDHC");
|
||||
} else {
|
||||
Serial.println("UNKNOWN");
|
||||
}
|
||||
uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
|
||||
Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);
|
||||
Serial.printf("Total space: %lluMB\r\n", SD_MMC.totalBytes() / (1024 * 1024));
|
||||
Serial.printf("Used space: %lluMB\r\n", SD_MMC.usedBytes() / (1024 * 1024));
|
||||
}
|
||||
|
||||
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
|
||||
Serial.printf("Listing directory: %s\n", dirname);
|
||||
|
||||
File root = fs.open(dirname);
|
||||
if(!root){
|
||||
Serial.println("Failed to open directory");
|
||||
return;
|
||||
}
|
||||
if(!root.isDirectory()){
|
||||
Serial.println("Not a directory");
|
||||
return;
|
||||
}
|
||||
|
||||
File file = root.openNextFile();
|
||||
while(file){
|
||||
if(file.isDirectory()){
|
||||
Serial.print(" DIR : ");
|
||||
Serial.println(file.name());
|
||||
if(levels){
|
||||
listDir(fs, file.path(), levels -1);
|
||||
}
|
||||
} else {
|
||||
Serial.print(" FILE: ");
|
||||
Serial.print(file.name());
|
||||
Serial.print(" SIZE: ");
|
||||
Serial.println(file.size());
|
||||
}
|
||||
file = root.openNextFile();
|
||||
}
|
||||
}
|
||||
|
||||
void createDir(fs::FS &fs, const char * path){
|
||||
Serial.printf("Creating Dir: %s\n", path);
|
||||
if(fs.mkdir(path)){
|
||||
Serial.println("Dir created");
|
||||
} else {
|
||||
Serial.println("mkdir failed");
|
||||
}
|
||||
}
|
||||
|
||||
void removeDir(fs::FS &fs, const char * path){
|
||||
Serial.printf("Removing Dir: %s\n", path);
|
||||
if(fs.rmdir(path)){
|
||||
Serial.println("Dir removed");
|
||||
} else {
|
||||
Serial.println("rmdir failed");
|
||||
}
|
||||
}
|
||||
|
||||
void readFile(fs::FS &fs, const char * path){
|
||||
Serial.printf("Reading file: %s\n", path);
|
||||
|
||||
File file = fs.open(path);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file for reading");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.print("Read from file: ");
|
||||
while(file.available()){
|
||||
Serial.write(file.read());
|
||||
}
|
||||
}
|
||||
|
||||
void writeFile(fs::FS &fs, const char * path, const char * message){
|
||||
Serial.printf("Writing file: %s\n", path);
|
||||
|
||||
File file = fs.open(path, FILE_WRITE);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file for writing");
|
||||
return;
|
||||
}
|
||||
if(file.print(message)){
|
||||
Serial.println("File written");
|
||||
} else {
|
||||
Serial.println("Write failed");
|
||||
}
|
||||
}
|
||||
|
||||
void appendFile(fs::FS &fs, const char * path, const char * message){
|
||||
Serial.printf("Appending to file: %s\n", path);
|
||||
|
||||
File file = fs.open(path, FILE_APPEND);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file for appending");
|
||||
return;
|
||||
}
|
||||
if(file.print(message)){
|
||||
Serial.println("Message appended");
|
||||
} else {
|
||||
Serial.println("Append failed");
|
||||
}
|
||||
}
|
||||
|
||||
void renameFile(fs::FS &fs, const char * path1, const char * path2){
|
||||
Serial.printf("Renaming file %s to %s\n", path1, path2);
|
||||
if (fs.rename(path1, path2)) {
|
||||
Serial.println("File renamed");
|
||||
} else {
|
||||
Serial.println("Rename failed");
|
||||
}
|
||||
}
|
||||
|
||||
void deleteFile(fs::FS &fs, const char * path){
|
||||
Serial.printf("Deleting file: %s\n", path);
|
||||
if(fs.remove(path)){
|
||||
Serial.println("File deleted");
|
||||
} else {
|
||||
Serial.println("Delete failed");
|
||||
}
|
||||
}
|
||||
|
||||
void testFileIO(fs::FS &fs, const char * path){
|
||||
File file = fs.open(path);
|
||||
static uint8_t buf[512];
|
||||
size_t len = 0;
|
||||
uint32_t start = millis();
|
||||
uint32_t end = start;
|
||||
if(file){
|
||||
len = file.size();
|
||||
size_t flen = len;
|
||||
start = millis();
|
||||
while(len){
|
||||
size_t toRead = len;
|
||||
if(toRead > 512){
|
||||
toRead = 512;
|
||||
}
|
||||
file.read(buf, toRead);
|
||||
len -= toRead;
|
||||
}
|
||||
end = millis() - start;
|
||||
Serial.printf("%u bytes read for %u ms\r\n", flen, end);
|
||||
file.close();
|
||||
} else {
|
||||
Serial.println("Failed to open file for reading");
|
||||
}
|
||||
|
||||
file = fs.open(path, FILE_WRITE);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file for writing");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t i;
|
||||
start = millis();
|
||||
for(i=0; i<2048; i++){
|
||||
file.write(buf, 512);
|
||||
}
|
||||
end = millis() - start;
|
||||
Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
|
||||
file.close();
|
||||
}
|
||||
|
||||
void writejpg(fs::FS &fs, const char * path, const uint8_t *buf, size_t size){
|
||||
File file = fs.open(path, FILE_WRITE);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file for writing");
|
||||
return;
|
||||
}
|
||||
file.write(buf, size);
|
||||
Serial.printf("Saved file to path: %s\r\n", path);
|
||||
}
|
||||
|
||||
int readFileNum(fs::FS &fs, const char * dirname){
|
||||
File root = fs.open(dirname);
|
||||
if(!root){
|
||||
Serial.println("Failed to open directory");
|
||||
return -1;
|
||||
}
|
||||
if(!root.isDirectory()){
|
||||
Serial.println("Not a directory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
File file = root.openNextFile();
|
||||
int num=0;
|
||||
while(file){
|
||||
file = root.openNextFile();
|
||||
num++;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef __SD_READ_WRITE_H
|
||||
#define __SD_READ_WRITE_H
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "FS.h"
|
||||
#include "SD_MMC.h"
|
||||
|
||||
#define SD_MMC_CMD 38 //Please do not modify it.
|
||||
#define SD_MMC_CLK 39 //Please do not modify it.
|
||||
#define SD_MMC_D0 40 //Please do not modify it.
|
||||
|
||||
void sdmmcInit(void);
|
||||
|
||||
void listDir(fs::FS &fs, const char * dirname, uint8_t levels);
|
||||
void createDir(fs::FS &fs, const char * path);
|
||||
void removeDir(fs::FS &fs, const char * path);
|
||||
void readFile(fs::FS &fs, const char * path);
|
||||
void writeFile(fs::FS &fs, const char * path, const char * message);
|
||||
void appendFile(fs::FS &fs, const char * path, const char * message);
|
||||
void renameFile(fs::FS &fs, const char * path1, const char * path2);
|
||||
void deleteFile(fs::FS &fs, const char * path);
|
||||
void testFileIO(fs::FS &fs, const char * path);
|
||||
|
||||
void writejpg(fs::FS &fs, const char * path, const uint8_t *buf, size_t size);
|
||||
int readFileNum(fs::FS &fs, const char * dirname);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/**********************************************************************
|
||||
Filename : Camera and SDcard
|
||||
Description : Use the onboard buttons to take photo and save them to an SD card.
|
||||
Auther : www.freenove.com
|
||||
Modification: 2022/11/02
|
||||
**********************************************************************/
|
||||
#include "esp_camera.h"
|
||||
#define CAMERA_MODEL_ESP32S3_EYE
|
||||
#include "camera_pins.h"
|
||||
#include "ws2812.h"
|
||||
#include "sd_read_write.h"
|
||||
|
||||
#define BUTTON_PIN 0
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(false);
|
||||
Serial.println();
|
||||
pinMode(BUTTON_PIN, INPUT_PULLUP);
|
||||
ws2812Init();
|
||||
sdmmcInit();
|
||||
//removeDir(SD_MMC, "/camera");
|
||||
createDir(SD_MMC, "/camera");
|
||||
listDir(SD_MMC, "/camera", 0);
|
||||
if(cameraSetup()==1){
|
||||
ws2812SetColor(2);
|
||||
}
|
||||
else{
|
||||
ws2812SetColor(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if(digitalRead(BUTTON_PIN)==LOW){
|
||||
delay(20);
|
||||
if(digitalRead(BUTTON_PIN)==LOW){
|
||||
ws2812SetColor(3);
|
||||
while(digitalRead(BUTTON_PIN)==LOW);
|
||||
camera_fb_t * fb = NULL;
|
||||
fb = esp_camera_fb_get();
|
||||
if (fb != NULL) {
|
||||
int photo_index = readFileNum(SD_MMC, "/camera");
|
||||
if(photo_index!=-1)
|
||||
{
|
||||
String path = "/camera/" + String(photo_index) +".jpg";
|
||||
writejpg(SD_MMC, path.c_str(), fb->buf, fb->len);
|
||||
}
|
||||
esp_camera_fb_return(fb);
|
||||
}
|
||||
else {
|
||||
Serial.println("Camera capture failed.");
|
||||
}
|
||||
ws2812SetColor(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int cameraSetup(void) {
|
||||
camera_config_t config;
|
||||
config.ledc_channel = LEDC_CHANNEL_0;
|
||||
config.ledc_timer = LEDC_TIMER_0;
|
||||
config.pin_d0 = Y2_GPIO_NUM;
|
||||
config.pin_d1 = Y3_GPIO_NUM;
|
||||
config.pin_d2 = Y4_GPIO_NUM;
|
||||
config.pin_d3 = Y5_GPIO_NUM;
|
||||
config.pin_d4 = Y6_GPIO_NUM;
|
||||
config.pin_d5 = Y7_GPIO_NUM;
|
||||
config.pin_d6 = Y8_GPIO_NUM;
|
||||
config.pin_d7 = Y9_GPIO_NUM;
|
||||
config.pin_xclk = XCLK_GPIO_NUM;
|
||||
config.pin_pclk = PCLK_GPIO_NUM;
|
||||
config.pin_vsync = VSYNC_GPIO_NUM;
|
||||
config.pin_href = HREF_GPIO_NUM;
|
||||
config.pin_sccb_sda = SIOD_GPIO_NUM;
|
||||
config.pin_sccb_scl = SIOC_GPIO_NUM;
|
||||
config.pin_pwdn = PWDN_GPIO_NUM;
|
||||
config.pin_reset = RESET_GPIO_NUM;
|
||||
config.xclk_freq_hz = 20000000;
|
||||
config.frame_size = FRAMESIZE_UXGA;
|
||||
config.pixel_format = PIXFORMAT_JPEG; // for streaming
|
||||
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
|
||||
config.fb_location = CAMERA_FB_IN_PSRAM;
|
||||
config.jpeg_quality = 12;
|
||||
config.fb_count = 1;
|
||||
|
||||
// if PSRAM IC present, init with UXGA resolution and higher JPEG quality
|
||||
// for larger pre-allocated frame buffer.
|
||||
if(psramFound()){
|
||||
config.jpeg_quality = 10;
|
||||
config.fb_count = 2;
|
||||
config.grab_mode = CAMERA_GRAB_LATEST;
|
||||
} else {
|
||||
// Limit the frame size when PSRAM is not available
|
||||
config.frame_size = FRAMESIZE_SVGA;
|
||||
config.fb_location = CAMERA_FB_IN_DRAM;
|
||||
}
|
||||
|
||||
// camera init
|
||||
esp_err_t err = esp_camera_init(&config);
|
||||
if (err != ESP_OK) {
|
||||
Serial.printf("Camera init failed with error 0x%x", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sensor_t * s = esp_camera_sensor_get();
|
||||
// initial sensors are flipped vertically and colors are a bit saturated
|
||||
s->set_vflip(s, 1); // flip it back
|
||||
s->set_brightness(s, 1); // up the brightness just a bit
|
||||
s->set_saturation(s, 0); // lower the saturation
|
||||
|
||||
Serial.println("Camera configuration complete!");
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,273 @@
|
|||
|
||||
#if defined(CAMERA_MODEL_WROVER_KIT)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 21
|
||||
#define SIOD_GPIO_NUM 26
|
||||
#define SIOC_GPIO_NUM 27
|
||||
|
||||
#define Y9_GPIO_NUM 35
|
||||
#define Y8_GPIO_NUM 34
|
||||
#define Y7_GPIO_NUM 39
|
||||
#define Y6_GPIO_NUM 36
|
||||
#define Y5_GPIO_NUM 19
|
||||
#define Y4_GPIO_NUM 18
|
||||
#define Y3_GPIO_NUM 5
|
||||
#define Y2_GPIO_NUM 4
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 23
|
||||
#define PCLK_GPIO_NUM 22
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP_EYE)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 4
|
||||
#define SIOD_GPIO_NUM 18
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 36
|
||||
#define Y8_GPIO_NUM 37
|
||||
#define Y7_GPIO_NUM 38
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 35
|
||||
#define Y4_GPIO_NUM 14
|
||||
#define Y3_GPIO_NUM 13
|
||||
#define Y2_GPIO_NUM 34
|
||||
#define VSYNC_GPIO_NUM 5
|
||||
#define HREF_GPIO_NUM 27
|
||||
#define PCLK_GPIO_NUM 25
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_V2_PSRAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 22
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_WIDE)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 22
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_ESP32CAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 17
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_UNITCAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_AI_THINKER)
|
||||
#define PWDN_GPIO_NUM 32
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 0
|
||||
#define SIOD_GPIO_NUM 26
|
||||
#define SIOC_GPIO_NUM 27
|
||||
|
||||
#define Y9_GPIO_NUM 35
|
||||
#define Y8_GPIO_NUM 34
|
||||
#define Y7_GPIO_NUM 39
|
||||
#define Y6_GPIO_NUM 36
|
||||
#define Y5_GPIO_NUM 21
|
||||
#define Y4_GPIO_NUM 19
|
||||
#define Y3_GPIO_NUM 18
|
||||
#define Y2_GPIO_NUM 5
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 23
|
||||
#define PCLK_GPIO_NUM 22
|
||||
|
||||
#elif defined(CAMERA_MODEL_TTGO_T_JOURNAL)
|
||||
#define PWDN_GPIO_NUM 0
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 17
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32_CAM_BOARD)
|
||||
// The 18 pin header on the board has Y5 and Y3 swapped
|
||||
#define USE_BOARD_HEADER 0
|
||||
#define PWDN_GPIO_NUM 32
|
||||
#define RESET_GPIO_NUM 33
|
||||
#define XCLK_GPIO_NUM 4
|
||||
#define SIOD_GPIO_NUM 18
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 36
|
||||
#define Y8_GPIO_NUM 19
|
||||
#define Y7_GPIO_NUM 21
|
||||
#define Y6_GPIO_NUM 39
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y5_GPIO_NUM 13
|
||||
#else
|
||||
#define Y5_GPIO_NUM 35
|
||||
#endif
|
||||
#define Y4_GPIO_NUM 14
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y3_GPIO_NUM 35
|
||||
#else
|
||||
#define Y3_GPIO_NUM 13
|
||||
#endif
|
||||
#define Y2_GPIO_NUM 34
|
||||
#define VSYNC_GPIO_NUM 5
|
||||
#define HREF_GPIO_NUM 27
|
||||
#define PCLK_GPIO_NUM 25
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32S3_CAM_LCD)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 40
|
||||
#define SIOD_GPIO_NUM 17
|
||||
#define SIOC_GPIO_NUM 18
|
||||
|
||||
#define Y9_GPIO_NUM 39
|
||||
#define Y8_GPIO_NUM 41
|
||||
#define Y7_GPIO_NUM 42
|
||||
#define Y6_GPIO_NUM 12
|
||||
#define Y5_GPIO_NUM 3
|
||||
#define Y4_GPIO_NUM 14
|
||||
#define Y3_GPIO_NUM 47
|
||||
#define Y2_GPIO_NUM 13
|
||||
#define VSYNC_GPIO_NUM 21
|
||||
#define HREF_GPIO_NUM 38
|
||||
#define PCLK_GPIO_NUM 11
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32S2_CAM_BOARD)
|
||||
// The 18 pin header on the board has Y5 and Y3 swapped
|
||||
#define USE_BOARD_HEADER 0
|
||||
#define PWDN_GPIO_NUM 1
|
||||
#define RESET_GPIO_NUM 2
|
||||
#define XCLK_GPIO_NUM 42
|
||||
#define SIOD_GPIO_NUM 41
|
||||
#define SIOC_GPIO_NUM 18
|
||||
|
||||
#define Y9_GPIO_NUM 16
|
||||
#define Y8_GPIO_NUM 39
|
||||
#define Y7_GPIO_NUM 40
|
||||
#define Y6_GPIO_NUM 15
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y5_GPIO_NUM 12
|
||||
#else
|
||||
#define Y5_GPIO_NUM 13
|
||||
#endif
|
||||
#define Y4_GPIO_NUM 5
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y3_GPIO_NUM 13
|
||||
#else
|
||||
#define Y3_GPIO_NUM 12
|
||||
#endif
|
||||
#define Y2_GPIO_NUM 14
|
||||
#define VSYNC_GPIO_NUM 38
|
||||
#define HREF_GPIO_NUM 4
|
||||
#define PCLK_GPIO_NUM 3
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32S3_EYE)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 15
|
||||
#define SIOD_GPIO_NUM 4
|
||||
#define SIOC_GPIO_NUM 5
|
||||
|
||||
#define Y2_GPIO_NUM 11
|
||||
#define Y3_GPIO_NUM 9
|
||||
#define Y4_GPIO_NUM 8
|
||||
#define Y5_GPIO_NUM 10
|
||||
#define Y6_GPIO_NUM 12
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y8_GPIO_NUM 17
|
||||
#define Y9_GPIO_NUM 16
|
||||
|
||||
#define VSYNC_GPIO_NUM 6
|
||||
#define HREF_GPIO_NUM 7
|
||||
#define PCLK_GPIO_NUM 13
|
||||
|
||||
#else
|
||||
#error "Camera model not selected"
|
||||
#endif
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
#include "sd_read_write.h"
|
||||
|
||||
void sdmmcInit(void){
|
||||
SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
|
||||
if (!SD_MMC.begin("/sdcard", true, true, SDMMC_FREQ_DEFAULT, 5)) {
|
||||
Serial.println("Card Mount Failed");
|
||||
return;
|
||||
}
|
||||
uint8_t cardType = SD_MMC.cardType();
|
||||
if(cardType == CARD_NONE){
|
||||
Serial.println("No SD_MMC card attached");
|
||||
return;
|
||||
}
|
||||
Serial.print("SD_MMC Card Type: ");
|
||||
if(cardType == CARD_MMC){
|
||||
Serial.println("MMC");
|
||||
} else if(cardType == CARD_SD){
|
||||
Serial.println("SDSC");
|
||||
} else if(cardType == CARD_SDHC){
|
||||
Serial.println("SDHC");
|
||||
} else {
|
||||
Serial.println("UNKNOWN");
|
||||
}
|
||||
uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
|
||||
Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);
|
||||
Serial.printf("Total space: %lluMB\r\n", SD_MMC.totalBytes() / (1024 * 1024));
|
||||
Serial.printf("Used space: %lluMB\r\n", SD_MMC.usedBytes() / (1024 * 1024));
|
||||
}
|
||||
|
||||
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
|
||||
Serial.printf("Listing directory: %s\n", dirname);
|
||||
|
||||
File root = fs.open(dirname);
|
||||
if(!root){
|
||||
Serial.println("Failed to open directory");
|
||||
return;
|
||||
}
|
||||
if(!root.isDirectory()){
|
||||
Serial.println("Not a directory");
|
||||
return;
|
||||
}
|
||||
|
||||
File file = root.openNextFile();
|
||||
while(file){
|
||||
if(file.isDirectory()){
|
||||
Serial.print(" DIR : ");
|
||||
Serial.println(file.name());
|
||||
if(levels){
|
||||
listDir(fs, file.path(), levels -1);
|
||||
}
|
||||
} else {
|
||||
Serial.print(" FILE: ");
|
||||
Serial.print(file.name());
|
||||
Serial.print(" SIZE: ");
|
||||
Serial.println(file.size());
|
||||
}
|
||||
file = root.openNextFile();
|
||||
}
|
||||
}
|
||||
|
||||
void createDir(fs::FS &fs, const char * path){
|
||||
Serial.printf("Creating Dir: %s\n", path);
|
||||
if(fs.mkdir(path)){
|
||||
Serial.println("Dir created");
|
||||
} else {
|
||||
Serial.println("mkdir failed");
|
||||
}
|
||||
}
|
||||
|
||||
void removeDir(fs::FS &fs, const char * path){
|
||||
Serial.printf("Removing Dir: %s\n", path);
|
||||
if(fs.rmdir(path)){
|
||||
Serial.println("Dir removed");
|
||||
} else {
|
||||
Serial.println("rmdir failed");
|
||||
}
|
||||
}
|
||||
|
||||
void readFile(fs::FS &fs, const char * path){
|
||||
Serial.printf("Reading file: %s\n", path);
|
||||
|
||||
File file = fs.open(path);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file for reading");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.print("Read from file: ");
|
||||
while(file.available()){
|
||||
Serial.write(file.read());
|
||||
}
|
||||
}
|
||||
|
||||
void writeFile(fs::FS &fs, const char * path, const char * message){
|
||||
Serial.printf("Writing file: %s\n", path);
|
||||
|
||||
File file = fs.open(path, FILE_WRITE);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file for writing");
|
||||
return;
|
||||
}
|
||||
if(file.print(message)){
|
||||
Serial.println("File written");
|
||||
} else {
|
||||
Serial.println("Write failed");
|
||||
}
|
||||
}
|
||||
|
||||
void appendFile(fs::FS &fs, const char * path, const char * message){
|
||||
Serial.printf("Appending to file: %s\n", path);
|
||||
|
||||
File file = fs.open(path, FILE_APPEND);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file for appending");
|
||||
return;
|
||||
}
|
||||
if(file.print(message)){
|
||||
Serial.println("Message appended");
|
||||
} else {
|
||||
Serial.println("Append failed");
|
||||
}
|
||||
}
|
||||
|
||||
void renameFile(fs::FS &fs, const char * path1, const char * path2){
|
||||
Serial.printf("Renaming file %s to %s\n", path1, path2);
|
||||
if (fs.rename(path1, path2)) {
|
||||
Serial.println("File renamed");
|
||||
} else {
|
||||
Serial.println("Rename failed");
|
||||
}
|
||||
}
|
||||
|
||||
void deleteFile(fs::FS &fs, const char * path){
|
||||
Serial.printf("Deleting file: %s\n", path);
|
||||
if(fs.remove(path)){
|
||||
Serial.println("File deleted");
|
||||
} else {
|
||||
Serial.println("Delete failed");
|
||||
}
|
||||
}
|
||||
|
||||
void testFileIO(fs::FS &fs, const char * path){
|
||||
File file = fs.open(path);
|
||||
static uint8_t buf[512];
|
||||
size_t len = 0;
|
||||
uint32_t start = millis();
|
||||
uint32_t end = start;
|
||||
if(file){
|
||||
len = file.size();
|
||||
size_t flen = len;
|
||||
start = millis();
|
||||
while(len){
|
||||
size_t toRead = len;
|
||||
if(toRead > 512){
|
||||
toRead = 512;
|
||||
}
|
||||
file.read(buf, toRead);
|
||||
len -= toRead;
|
||||
}
|
||||
end = millis() - start;
|
||||
Serial.printf("%u bytes read for %u ms\r\n", flen, end);
|
||||
file.close();
|
||||
} else {
|
||||
Serial.println("Failed to open file for reading");
|
||||
}
|
||||
|
||||
file = fs.open(path, FILE_WRITE);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file for writing");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t i;
|
||||
start = millis();
|
||||
for(i=0; i<2048; i++){
|
||||
file.write(buf, 512);
|
||||
}
|
||||
end = millis() - start;
|
||||
Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
|
||||
file.close();
|
||||
}
|
||||
|
||||
void writejpg(fs::FS &fs, const char * path, const uint8_t *buf, size_t size){
|
||||
File file = fs.open(path, FILE_WRITE);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file for writing");
|
||||
return;
|
||||
}
|
||||
file.write(buf, size);
|
||||
Serial.printf("Saved file to path: %s\r\n", path);
|
||||
}
|
||||
|
||||
int readFileNum(fs::FS &fs, const char * dirname){
|
||||
File root = fs.open(dirname);
|
||||
if(!root){
|
||||
Serial.println("Failed to open directory");
|
||||
return -1;
|
||||
}
|
||||
if(!root.isDirectory()){
|
||||
Serial.println("Not a directory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
File file = root.openNextFile();
|
||||
int num=0;
|
||||
while(file){
|
||||
file = root.openNextFile();
|
||||
num++;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef __SD_READ_WRITE_H
|
||||
#define __SD_READ_WRITE_H
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "FS.h"
|
||||
#include "SD_MMC.h"
|
||||
|
||||
#define SD_MMC_CMD 38 //Please do not modify it.
|
||||
#define SD_MMC_CLK 39 //Please do not modify it.
|
||||
#define SD_MMC_D0 40 //Please do not modify it.
|
||||
|
||||
void sdmmcInit(void);
|
||||
|
||||
void listDir(fs::FS &fs, const char * dirname, uint8_t levels);
|
||||
void createDir(fs::FS &fs, const char * path);
|
||||
void removeDir(fs::FS &fs, const char * path);
|
||||
void readFile(fs::FS &fs, const char * path);
|
||||
void writeFile(fs::FS &fs, const char * path, const char * message);
|
||||
void appendFile(fs::FS &fs, const char * path, const char * message);
|
||||
void renameFile(fs::FS &fs, const char * path1, const char * path2);
|
||||
void deleteFile(fs::FS &fs, const char * path);
|
||||
void testFileIO(fs::FS &fs, const char * path);
|
||||
|
||||
void writejpg(fs::FS &fs, const char * path, const uint8_t *buf, size_t size);
|
||||
int readFileNum(fs::FS &fs, const char * dirname);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
#include "ws2812.h"
|
||||
|
||||
Freenove_ESP32_WS2812 strip = Freenove_ESP32_WS2812(1, WS2812_PIN, 1, TYPE_GRB);
|
||||
|
||||
void ws2812Init(void)
|
||||
{
|
||||
strip.begin();
|
||||
strip.setBrightness(10);
|
||||
ws2812SetColor(0);
|
||||
}
|
||||
void ws2812SetColor(int color)
|
||||
{
|
||||
if(color==0)
|
||||
{
|
||||
strip.setLedColorData(0, 0, 0, 0);
|
||||
}
|
||||
else if(color==1)
|
||||
{
|
||||
strip.setLedColorData(0, 255, 0, 0);
|
||||
}
|
||||
else if(color==2)
|
||||
{
|
||||
strip.setLedColorData(0, 0, 255, 0);
|
||||
}
|
||||
else if(color==3)
|
||||
{
|
||||
strip.setLedColorData(0, 0, 0, 255);
|
||||
}
|
||||
strip.show();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef __WS2812_H
|
||||
#define __WS2812_H
|
||||
|
||||
#include "Freenove_WS2812_Lib_for_ESP32.h"
|
||||
|
||||
#define WS2812_PIN 48
|
||||
|
||||
void ws2812Init(void);
|
||||
void ws2812SetColor(int color);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
/**********************************************************************
|
||||
Filename : Camera Tcp Serrver
|
||||
Description : Users use Freenove's APP to view images from ESP32S3's camera
|
||||
Auther : www.freenove.com
|
||||
Modification: 2024/07/01
|
||||
**********************************************************************/
|
||||
#include "esp_camera.h"
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <WiFiAP.h>
|
||||
|
||||
#define CAMERA_MODEL_ESP32S3_EYE
|
||||
#include "camera_pins.h"
|
||||
#define LED_BUILT_IN 2
|
||||
|
||||
const char* ssid_Router = "********";
|
||||
const char* password_Router = "********";
|
||||
const char *ssid_AP = "********";
|
||||
const char *password_AP = "********";
|
||||
|
||||
WiFiServer server_Cmd(5000);
|
||||
WiFiServer server_Camera(8000);
|
||||
extern TaskHandle_t loopTaskHandle;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(false);
|
||||
Serial.println();
|
||||
pinMode(LED_BUILT_IN, OUTPUT);
|
||||
cameraSetup();
|
||||
|
||||
WiFi.softAP(ssid_AP, password_AP);
|
||||
IPAddress myIP = WiFi.softAPIP();
|
||||
Serial.print("AP IP address: ");
|
||||
Serial.println(myIP);
|
||||
server_Camera.begin(8000);
|
||||
server_Cmd.begin(5000);
|
||||
/////////////////////////////////////////////////////
|
||||
WiFi.begin(ssid_Router, password_Router);
|
||||
Serial.print("Connecting ");
|
||||
Serial.print(ssid_Router);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
while (WiFi.STA.hasIP() != true) {
|
||||
Serial.print(".");
|
||||
delay(500);
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
/////////////////////////////////////////////////////
|
||||
Serial.print("Camera Ready! Use '");
|
||||
Serial.print(WiFi.softAPIP());
|
||||
Serial.print(" or ");
|
||||
Serial.print(WiFi.localIP());
|
||||
Serial.println("' to connect in Freenove app.");
|
||||
|
||||
disableCore0WDT();
|
||||
xTaskCreateUniversal(loopTask_Cmd, "loopTask_Cmd", 8192, NULL, 1, &loopTaskHandle, 0); //loopTask_Cmd uses core 0.
|
||||
xTaskCreateUniversal(loopTask_Blink, "loopTask_Blink", 8192, NULL, 1, &loopTaskHandle, 0);//loopTask_Blink uses core 0.
|
||||
}
|
||||
//task loop uses core 1.
|
||||
void loop() {
|
||||
WiFiClient client = server_Camera.accept(); // listen for incoming clients
|
||||
if (client) { // if you get a client,
|
||||
Serial.println("Camera Server connected to a client.");// print a message out the serial port
|
||||
String currentLine = ""; // make a String to hold incoming data from the client
|
||||
while (client.connected()) { // loop while the client's connected
|
||||
camera_fb_t * fb = NULL;
|
||||
while (client.connected()) {
|
||||
fb = esp_camera_fb_get();
|
||||
if (fb != NULL) {
|
||||
uint8_t slen[4];
|
||||
slen[0] = fb->len >> 0;
|
||||
slen[1] = fb->len >> 8;
|
||||
slen[2] = fb->len >> 16;
|
||||
slen[3] = fb->len >> 24;
|
||||
client.write(slen, 4);
|
||||
client.write(fb->buf, fb->len);
|
||||
esp_camera_fb_return(fb);
|
||||
}
|
||||
else {
|
||||
Serial.println("Camera Error");
|
||||
}
|
||||
}
|
||||
}
|
||||
// close the connection:
|
||||
client.stop();
|
||||
Serial.println("Camera Client Disconnected.");
|
||||
}
|
||||
}
|
||||
|
||||
void loopTask_Cmd(void *pvParameters) {
|
||||
Serial.println("Task Cmd_Server is starting ... ");
|
||||
while (1) {
|
||||
WiFiClient client = server_Cmd.accept(); // listen for incoming clients
|
||||
if (client) { // if you get a client,
|
||||
Serial.println("Command Server connected to a client.");// print a message out the serial port
|
||||
String currentLine = ""; // make a String to hold incoming data from the client
|
||||
while (client.connected()) { // loop while the client's connected
|
||||
if (client.available()) { // if there's bytes to read from the client,
|
||||
char c = client.read(); // read a byte, then
|
||||
client.write(c);
|
||||
Serial.write(c); // print it out the serial monitor
|
||||
if (c == '\n') { // if the byte is a newline character
|
||||
currentLine = "";
|
||||
}
|
||||
else {
|
||||
currentLine += c; // add it to the end of the currentLine
|
||||
}
|
||||
}
|
||||
}
|
||||
// close the connection:
|
||||
client.stop();
|
||||
Serial.println("Command Client Disconnected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
void loopTask_Blink(void *pvParameters) {
|
||||
Serial.println("Task Blink is starting ... ");
|
||||
while (1) {
|
||||
digitalWrite(LED_BUILT_IN, !digitalRead(LED_BUILT_IN));
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
void cameraSetup() {
|
||||
camera_config_t config;
|
||||
config.ledc_channel = LEDC_CHANNEL_0;
|
||||
config.ledc_timer = LEDC_TIMER_0;
|
||||
config.pin_d0 = Y2_GPIO_NUM;
|
||||
config.pin_d1 = Y3_GPIO_NUM;
|
||||
config.pin_d2 = Y4_GPIO_NUM;
|
||||
config.pin_d3 = Y5_GPIO_NUM;
|
||||
config.pin_d4 = Y6_GPIO_NUM;
|
||||
config.pin_d5 = Y7_GPIO_NUM;
|
||||
config.pin_d6 = Y8_GPIO_NUM;
|
||||
config.pin_d7 = Y9_GPIO_NUM;
|
||||
config.pin_xclk = XCLK_GPIO_NUM;
|
||||
config.pin_pclk = PCLK_GPIO_NUM;
|
||||
config.pin_vsync = VSYNC_GPIO_NUM;
|
||||
config.pin_href = HREF_GPIO_NUM;
|
||||
config.pin_sccb_sda = SIOD_GPIO_NUM;
|
||||
config.pin_sccb_scl = SIOC_GPIO_NUM;
|
||||
config.pin_pwdn = PWDN_GPIO_NUM;
|
||||
config.pin_reset = RESET_GPIO_NUM;
|
||||
config.xclk_freq_hz = 20000000;
|
||||
config.frame_size = FRAMESIZE_UXGA;
|
||||
config.pixel_format = PIXFORMAT_JPEG; // for streaming
|
||||
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
|
||||
config.fb_location = CAMERA_FB_IN_PSRAM;
|
||||
config.jpeg_quality = 12;
|
||||
config.fb_count = 1;
|
||||
|
||||
// if PSRAM IC present, init with UXGA resolution and higher JPEG quality
|
||||
// for larger pre-allocated frame buffer.
|
||||
if(psramFound()){
|
||||
config.jpeg_quality = 10;
|
||||
config.fb_count = 2;
|
||||
config.grab_mode = CAMERA_GRAB_LATEST;
|
||||
} else {
|
||||
// Limit the frame size when PSRAM is not available
|
||||
config.frame_size = FRAMESIZE_SVGA;
|
||||
config.fb_location = CAMERA_FB_IN_DRAM;
|
||||
}
|
||||
|
||||
// camera init
|
||||
esp_err_t err = esp_camera_init(&config);
|
||||
if (err != ESP_OK) {
|
||||
Serial.printf("Camera init failed with error 0x%x", err);
|
||||
return;
|
||||
}
|
||||
|
||||
sensor_t * s = esp_camera_sensor_get();
|
||||
// initial sensors are flipped vertically and colors are a bit saturated
|
||||
s->set_vflip(s, 1); // flip it back
|
||||
s->set_brightness(s, 1); // up the brightness just a bit
|
||||
s->set_saturation(s, 0); // lower the saturation
|
||||
|
||||
Serial.println("Camera configuration complete!");
|
||||
}
|
||||
|
|
@ -0,0 +1,273 @@
|
|||
|
||||
#if defined(CAMERA_MODEL_WROVER_KIT)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 21
|
||||
#define SIOD_GPIO_NUM 26
|
||||
#define SIOC_GPIO_NUM 27
|
||||
|
||||
#define Y9_GPIO_NUM 35
|
||||
#define Y8_GPIO_NUM 34
|
||||
#define Y7_GPIO_NUM 39
|
||||
#define Y6_GPIO_NUM 36
|
||||
#define Y5_GPIO_NUM 19
|
||||
#define Y4_GPIO_NUM 18
|
||||
#define Y3_GPIO_NUM 5
|
||||
#define Y2_GPIO_NUM 4
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 23
|
||||
#define PCLK_GPIO_NUM 22
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP_EYE)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 4
|
||||
#define SIOD_GPIO_NUM 18
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 36
|
||||
#define Y8_GPIO_NUM 37
|
||||
#define Y7_GPIO_NUM 38
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 35
|
||||
#define Y4_GPIO_NUM 14
|
||||
#define Y3_GPIO_NUM 13
|
||||
#define Y2_GPIO_NUM 34
|
||||
#define VSYNC_GPIO_NUM 5
|
||||
#define HREF_GPIO_NUM 27
|
||||
#define PCLK_GPIO_NUM 25
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_V2_PSRAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 22
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_WIDE)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 22
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_ESP32CAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 17
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_UNITCAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_AI_THINKER)
|
||||
#define PWDN_GPIO_NUM 32
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 0
|
||||
#define SIOD_GPIO_NUM 26
|
||||
#define SIOC_GPIO_NUM 27
|
||||
|
||||
#define Y9_GPIO_NUM 35
|
||||
#define Y8_GPIO_NUM 34
|
||||
#define Y7_GPIO_NUM 39
|
||||
#define Y6_GPIO_NUM 36
|
||||
#define Y5_GPIO_NUM 21
|
||||
#define Y4_GPIO_NUM 19
|
||||
#define Y3_GPIO_NUM 18
|
||||
#define Y2_GPIO_NUM 5
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 23
|
||||
#define PCLK_GPIO_NUM 22
|
||||
|
||||
#elif defined(CAMERA_MODEL_TTGO_T_JOURNAL)
|
||||
#define PWDN_GPIO_NUM 0
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 17
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32_CAM_BOARD)
|
||||
// The 18 pin header on the board has Y5 and Y3 swapped
|
||||
#define USE_BOARD_HEADER 0
|
||||
#define PWDN_GPIO_NUM 32
|
||||
#define RESET_GPIO_NUM 33
|
||||
#define XCLK_GPIO_NUM 4
|
||||
#define SIOD_GPIO_NUM 18
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 36
|
||||
#define Y8_GPIO_NUM 19
|
||||
#define Y7_GPIO_NUM 21
|
||||
#define Y6_GPIO_NUM 39
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y5_GPIO_NUM 13
|
||||
#else
|
||||
#define Y5_GPIO_NUM 35
|
||||
#endif
|
||||
#define Y4_GPIO_NUM 14
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y3_GPIO_NUM 35
|
||||
#else
|
||||
#define Y3_GPIO_NUM 13
|
||||
#endif
|
||||
#define Y2_GPIO_NUM 34
|
||||
#define VSYNC_GPIO_NUM 5
|
||||
#define HREF_GPIO_NUM 27
|
||||
#define PCLK_GPIO_NUM 25
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32S3_CAM_LCD)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 40
|
||||
#define SIOD_GPIO_NUM 17
|
||||
#define SIOC_GPIO_NUM 18
|
||||
|
||||
#define Y9_GPIO_NUM 39
|
||||
#define Y8_GPIO_NUM 41
|
||||
#define Y7_GPIO_NUM 42
|
||||
#define Y6_GPIO_NUM 12
|
||||
#define Y5_GPIO_NUM 3
|
||||
#define Y4_GPIO_NUM 14
|
||||
#define Y3_GPIO_NUM 47
|
||||
#define Y2_GPIO_NUM 13
|
||||
#define VSYNC_GPIO_NUM 21
|
||||
#define HREF_GPIO_NUM 38
|
||||
#define PCLK_GPIO_NUM 11
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32S2_CAM_BOARD)
|
||||
// The 18 pin header on the board has Y5 and Y3 swapped
|
||||
#define USE_BOARD_HEADER 0
|
||||
#define PWDN_GPIO_NUM 1
|
||||
#define RESET_GPIO_NUM 2
|
||||
#define XCLK_GPIO_NUM 42
|
||||
#define SIOD_GPIO_NUM 41
|
||||
#define SIOC_GPIO_NUM 18
|
||||
|
||||
#define Y9_GPIO_NUM 16
|
||||
#define Y8_GPIO_NUM 39
|
||||
#define Y7_GPIO_NUM 40
|
||||
#define Y6_GPIO_NUM 15
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y5_GPIO_NUM 12
|
||||
#else
|
||||
#define Y5_GPIO_NUM 13
|
||||
#endif
|
||||
#define Y4_GPIO_NUM 5
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y3_GPIO_NUM 13
|
||||
#else
|
||||
#define Y3_GPIO_NUM 12
|
||||
#endif
|
||||
#define Y2_GPIO_NUM 14
|
||||
#define VSYNC_GPIO_NUM 38
|
||||
#define HREF_GPIO_NUM 4
|
||||
#define PCLK_GPIO_NUM 3
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32S3_EYE)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 15
|
||||
#define SIOD_GPIO_NUM 4
|
||||
#define SIOC_GPIO_NUM 5
|
||||
|
||||
#define Y2_GPIO_NUM 11
|
||||
#define Y3_GPIO_NUM 9
|
||||
#define Y4_GPIO_NUM 8
|
||||
#define Y5_GPIO_NUM 10
|
||||
#define Y6_GPIO_NUM 12
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y8_GPIO_NUM 17
|
||||
#define Y9_GPIO_NUM 16
|
||||
|
||||
#define VSYNC_GPIO_NUM 6
|
||||
#define HREF_GPIO_NUM 7
|
||||
#define PCLK_GPIO_NUM 13
|
||||
|
||||
#else
|
||||
#error "Camera model not selected"
|
||||
#endif
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
Binary file not shown.
|
|
@ -0,0 +1,29 @@
|
|||
# ch343 linux serial driver
|
||||
|
||||
## Description
|
||||
|
||||
USB to UART(s) chip ch342/ch343/ch344/ch347/ch9101/ch9102/ch9103 are fully compliant to the Communications Device Class (CDC) standard, they will work with a standard CDC-ACM driver (CDC - Abstract Control Model). Linux operating systems supply a default CDC-ACM driver that can be used with these USB UART devices. In Linux, this driver file name is cdc-acm.
|
||||
|
||||
The CDC-ACM driver has limited capabilities to control specific devices. This generic driver does not have any knowledge about specific device protocols. Because of this, device manufacturers can create an alternate, or custom driver that is capable of accessing the device specific function sets, such as hardware flow control or GPIO functions.
|
||||
|
||||
If you use this VCP driver, please check that the CDC-ACM driver was not installed for the USB UART devices mentioned above. You can use command "ls /dev/ttyACM*" to confirm that, to remove the CDC-ACM driver, use command "rmmod cdc-acm".
|
||||
|
||||
This directory contains 2 parts, ch343 driver and gpio testing utility. This driver and application support USB to single serial port chip ch343/ch347/ch9101/ch9102, USB to dual serial ports chip ch342/ch347/ch9103, USB to quad serial ports chip ch344, etc.
|
||||
|
||||
1. Open "Terminal"
|
||||
2. Switch to "driver" directory
|
||||
3. Compile the driver using "make", you will see the module "ch343.ko" if successful
|
||||
4. Type "sudo make load" or "sudo insmod ch343.ko" to load the driver dynamically
|
||||
5. Type "sudo make unload" or "sudo rmmod ch343.ko" to unload the driver
|
||||
6. Type "sudo make install" to make the driver work permanently
|
||||
7. Type "sudo make uninstall" to remove the driver
|
||||
8. You can refer to the link below to acquire uart application, you can use gcc or Cross-compile with cross-gcc
|
||||
https://github.com/WCHSoftGroup/tty_uart
|
||||
|
||||
Before the driver works, you should make sure that the usb device has been plugged in and is working properly, you can use shell command "lsusb" or "dmesg" to confirm that, USB VID of these devices are [1A86], you can view all IDs from the id table which defined in "ch343.c".
|
||||
|
||||
If the device works well, the driver will created tty devices named "ttyCH343USBx" in /dev directory. Operating the device in the /dev directory under Linux requires root permission by default, if users want to access the device in a non root mode, they can create udev rule file related to the device.
|
||||
|
||||
## Note
|
||||
|
||||
Any question, you can send feedback to mail: tech@wch.cn
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
ifeq ($(KERNELRELEASE), )
|
||||
KERNELDIR := /lib/modules/$(shell uname -r)/build
|
||||
PWD :=$(shell pwd)
|
||||
default:
|
||||
$(MAKE) -C $(KERNELDIR) M=$(PWD)
|
||||
clean:
|
||||
rm -rf *.mk .tmp_versions Module.symvers *.mod.c *.o *.ko .*.cmd Module.markers modules.order *.a *.mod
|
||||
load:
|
||||
insmod ch343.ko
|
||||
unload:
|
||||
rmmod ch343
|
||||
install: default
|
||||
mkdir -p /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial
|
||||
cp -f ./ch343.ko /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial
|
||||
echo "ch343\n" >> /etc/modules
|
||||
depmod -a
|
||||
uninstall:
|
||||
rm -rf /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ch343.ko
|
||||
depmod -a
|
||||
else
|
||||
obj-m := ch343.o
|
||||
endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,243 @@
|
|||
#ifndef _CH343_H
|
||||
#define _CH343_H
|
||||
|
||||
/*
|
||||
* Baud rate and default timeout
|
||||
*/
|
||||
#define DEFAULT_BAUD_RATE 9600
|
||||
#define DEFAULT_TIMEOUT 2000
|
||||
|
||||
/*
|
||||
* CMSPAR, some architectures can't have space and mark parity.
|
||||
*/
|
||||
|
||||
#ifndef CMSPAR
|
||||
#define CMSPAR 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Major and minor numbers.
|
||||
*/
|
||||
|
||||
#define CH343_TTY_MAJOR 170
|
||||
#define CH343_TTY_MINORS 256
|
||||
|
||||
#define USB_MINOR_BASE 70
|
||||
|
||||
/*
|
||||
* Requests.
|
||||
*/
|
||||
|
||||
#define USB_RT_CH343 (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
|
||||
|
||||
#define CMD_R 0x95
|
||||
#define CMD_W 0x9A
|
||||
#define CMD_C1 0xA1
|
||||
#define CMD_C2 0xA4
|
||||
#define CMD_C3 0x05
|
||||
#define CMD_C4 0xA8
|
||||
#define CMD_C5 0x5E
|
||||
#define CMD_C6 0x5F
|
||||
|
||||
#define CH343_CTO_O 0x10
|
||||
#define CH343_CTO_D 0x20
|
||||
#define CH343_CTO_R 0x40
|
||||
#define CH343_CTO_A 0x80
|
||||
#define CH343_CTI_C 0x01
|
||||
#define CH343_CTI_DS 0x02
|
||||
#define CH343_CTI_R 0x04
|
||||
#define CH343_CTI_DC 0x08
|
||||
#define CH343_CTI_ST 0x0f
|
||||
|
||||
#define CH343_CTT_M 0x08
|
||||
#define CH343_CTT_F 0x44
|
||||
#define CH343_CTT_P 0x04
|
||||
#define CH343_CTT_O 0x02
|
||||
|
||||
#define CH343_LO 0x02
|
||||
#define CH343_LE 0x04
|
||||
#define CH343_LB
|
||||
#define CH343_LP 0x00
|
||||
#define CH343_LF 0x40
|
||||
#define CH343_LM 0x08
|
||||
|
||||
#define CH343_L_R_CT 0x80
|
||||
#define CH343_L_R_CL 0x04
|
||||
#define CH343_L_R_T 0x08
|
||||
|
||||
#define CH343_L_E_R 0x80
|
||||
#define CH343_L_E_T 0x40
|
||||
#define CH343_L_P_S 0x38
|
||||
#define CH343_L_P_M 0x28
|
||||
#define CH343_L_P_E 0x18
|
||||
#define CH343_L_P_O 0x08
|
||||
#define CH343_L_SB 0x04
|
||||
#define CH343_L_C8 0x03
|
||||
#define CH343_L_C7 0x02
|
||||
#define CH343_L_C6 0x01
|
||||
#define CH343_L_C5 0x00
|
||||
|
||||
#define CH343_N_B 0x80
|
||||
#define CH343_N_AB 0x10
|
||||
|
||||
/*
|
||||
* Internal driver structures.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The only reason to have several buffers is to accommodate assumptions
|
||||
* in line disciplines. They ask for empty space amount, receive our URB size,
|
||||
* and proceed to issue several 1-character writes, assuming they will fit.
|
||||
* The very first write takes a complete URB. Fortunately, this only happens
|
||||
* when processing onlcr, so we only need 2 buffers. These values must be
|
||||
* powers of 2.
|
||||
*/
|
||||
#define CH343_NW 16
|
||||
#define CH343_NR 16
|
||||
|
||||
struct ch343_wb {
|
||||
unsigned char *buf;
|
||||
dma_addr_t dmah;
|
||||
int len;
|
||||
int use;
|
||||
struct urb *urb;
|
||||
struct ch343 *instance;
|
||||
};
|
||||
|
||||
struct ch343_rb {
|
||||
int size;
|
||||
unsigned char *base;
|
||||
dma_addr_t dma;
|
||||
int index;
|
||||
struct ch343 *instance;
|
||||
};
|
||||
|
||||
struct usb_ch343_line_coding {
|
||||
__u32 dwDTERate;
|
||||
__u8 bCharFormat;
|
||||
#define USB_CH343_1_STOP_BITS 0
|
||||
#define USB_CH343_1_5_STOP_BITS 1
|
||||
#define USB_CH343_2_STOP_BITS 2
|
||||
|
||||
__u8 bParityType;
|
||||
#define USB_CH343_NO_PARITY 0
|
||||
#define USB_CH343_ODD_PARITY 1
|
||||
#define USB_CH343_EVEN_PARITY 2
|
||||
#define USB_CH343_MARK_PARITY 3
|
||||
#define USB_CH343_SPACE_PARITY 4
|
||||
|
||||
__u8 bDataBits;
|
||||
} __attribute__((packed));
|
||||
|
||||
typedef enum {
|
||||
CHIP_CH342F = 0x00,
|
||||
CHIP_CH342K,
|
||||
CHIP_CH343GP,
|
||||
CHIP_CH343G_AUTOBAUD,
|
||||
CHIP_CH343K,
|
||||
CHIP_CH343J,
|
||||
CHIP_CH344L,
|
||||
CHIP_CH344L_V2,
|
||||
CHIP_CH344Q,
|
||||
CHIP_CH347T,
|
||||
CHIP_CH9101UH,
|
||||
CHIP_CH9101RY,
|
||||
CHIP_CH9102F,
|
||||
CHIP_CH9102X,
|
||||
CHIP_CH9103M,
|
||||
CHIP_CH9104L,
|
||||
} CHIPTYPE;
|
||||
|
||||
struct gpioinfo {
|
||||
int group;
|
||||
int pin;
|
||||
};
|
||||
|
||||
struct ch343_gpio {
|
||||
int gpiocount;
|
||||
struct gpioinfo io[64];
|
||||
};
|
||||
|
||||
struct ch343_gpio ch343_gpios[] = {
|
||||
{ 0, {}},
|
||||
{ 0, {}},
|
||||
{ 0, {}},
|
||||
{ 0, {}},
|
||||
{ 0, {}},
|
||||
{ 0, {}},
|
||||
/* CH344L */
|
||||
{ 8, {}},
|
||||
/* CH344L-V2 */
|
||||
{ 8, {}},
|
||||
/* CH344Q */
|
||||
{ 8, {}},
|
||||
/* CH347T */
|
||||
{ 4, {}},
|
||||
/* CH9101UH */
|
||||
{ 5, {{3, 2}, {3, 3}, {1, 3}, {1, 2}, {1, 5}, {2, 4}}},
|
||||
/* CH9101RY */
|
||||
{ 4, {{1, 3}, {3, 3}, {3, 2}, {2, 4}}},
|
||||
/* CH9102F */
|
||||
{ 5, {{2, 1}, {2, 7}, {2, 4}, {2, 6}, {2, 3}}},
|
||||
/* CH9102X */
|
||||
{ 6, {{2, 3}, {2, 5}, {2, 1}, {2, 7}, {3, 0}, {2, 2}}},
|
||||
/* CH9103M */
|
||||
{12, {{1, 3}, {1, 2}, {3, 2}, {2, 6}, {1, 0}, {1, 6}, {2, 3}, {2, 5}, {3, 0}, {2, 2}, {1, 5}, {2, 4}}},
|
||||
/* CH9104L */
|
||||
{24, {}},
|
||||
};
|
||||
|
||||
struct ch343 {
|
||||
struct usb_device *dev; /* the corresponding usb device */
|
||||
struct usb_interface *control; /* control interface */
|
||||
struct usb_interface *data; /* data interface */
|
||||
struct tty_port port; /* our tty port data */
|
||||
struct urb *ctrlurb; /* urbs */
|
||||
u8 *ctrl_buffer; /* buffers of urbs */
|
||||
dma_addr_t ctrl_dma; /* dma handles of buffers */
|
||||
struct ch343_wb wb[CH343_NW];
|
||||
unsigned long read_urbs_free;
|
||||
struct urb *read_urbs[CH343_NR];
|
||||
struct ch343_rb read_buffers[CH343_NR];
|
||||
int rx_buflimit;
|
||||
int rx_endpoint;
|
||||
spinlock_t read_lock;
|
||||
int write_used; /* number of non-empty write buffers */
|
||||
int transmitting;
|
||||
spinlock_t write_lock;
|
||||
struct mutex mutex;
|
||||
bool disconnected;
|
||||
struct usb_ch343_line_coding line; /* bits, stop, parity */
|
||||
struct work_struct work; /* work queue entry for line discipline waking up */
|
||||
unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
|
||||
unsigned int ctrlout; /* output control lines (DTR, RTS) */
|
||||
struct async_icount iocount; /* counters for control line changes */
|
||||
struct async_icount oldcount; /* for comparison of counter */
|
||||
wait_queue_head_t wioctl; /* for ioctl */
|
||||
unsigned int writesize; /* max packet size for the output bulk endpoint */
|
||||
unsigned int readsize, ctrlsize; /* buffer sizes for freeing */
|
||||
unsigned int minor; /* ch343 minor number */
|
||||
unsigned char clocal; /* termios CLOCAL */
|
||||
unsigned int susp_count; /* number of suspended interfaces */
|
||||
u8 bInterval;
|
||||
struct usb_anchor delayed; /* writes queued for a device about to be woken */
|
||||
unsigned long quirks;
|
||||
u8 iface;
|
||||
CHIPTYPE chiptype;
|
||||
u16 idVendor;
|
||||
u16 idProduct;
|
||||
u8 gpio5dir;
|
||||
};
|
||||
|
||||
#define CDC_DATA_INTERFACE_TYPE 0x0a
|
||||
|
||||
/* constants describing various quirks and errors */
|
||||
#define NO_UNION_NORMAL BIT(0)
|
||||
#define SINGLE_RX_URB BIT(1)
|
||||
#define NO_CAP_LINE BIT(2)
|
||||
#define NO_DATA_INTERFACE BIT(4)
|
||||
#define IGNORE_DEVICE BIT(5)
|
||||
#define QUIRK_CONTROL_LINE_STATE BIT(6)
|
||||
#define CLEAR_HALT_CONDITIONS BIT(7)
|
||||
|
||||
#endif
|
||||
Binary file not shown.
|
|
@ -0,0 +1,5 @@
|
|||
For MAC users, the CH343 driver will always need to go to the official website to download the latest version,
|
||||
as older versions may not be suitable.
|
||||
|
||||
Below is the official download link:
|
||||
http://www.wch-ic.com/search?t=all&q=ch343
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 253 KiB |
|
|
@ -0,0 +1,58 @@
|
|||
Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License (CC BY-NC-SA 3.0)
|
||||
|
||||
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
|
||||
|
||||
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
|
||||
|
||||
1. Definitions
|
||||
|
||||
"Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License.
|
||||
"Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(g) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined above) for the purposes of this License.
|
||||
"Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership.
|
||||
"License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, Noncommercial, ShareAlike.
|
||||
"Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License.
|
||||
"Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast.
|
||||
"Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work.
|
||||
"You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
|
||||
"Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images.
|
||||
"Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium.
|
||||
2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws.
|
||||
|
||||
3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:
|
||||
|
||||
to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections;
|
||||
to create and Reproduce Adaptations provided that any such Adaptation, including any translation in any medium, takes reasonable steps to clearly label, demarcate or otherwise identify that changes were made to the original Work. For example, a translation could be marked "The original work was translated from English to Spanish," or a modification could indicate "The original work has been modified.";
|
||||
to Distribute and Publicly Perform the Work including as incorporated in Collections; and,
|
||||
to Distribute and Publicly Perform Adaptations.
|
||||
The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. Subject to Section 8(f), all rights not expressly granted by Licensor are hereby reserved, including but not limited to the rights described in Section 4(e).
|
||||
|
||||
4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:
|
||||
|
||||
You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(d), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(d), as requested.
|
||||
You may Distribute or Publicly Perform an Adaptation only under: (i) the terms of this License; (ii) a later version of this License with the same License Elements as this License; (iii) a Creative Commons jurisdiction license (either this or a later license version) that contains the same License Elements as this License (e.g., Attribution-NonCommercial-ShareAlike 3.0 US) ("Applicable License"). You must include a copy of, or the URI, for Applicable License with every copy of each Adaptation You Distribute or Publicly Perform. You may not offer or impose any terms on the Adaptation that restrict the terms of the Applicable License or the ability of the recipient of the Adaptation to exercise the rights granted to that recipient under the terms of the Applicable License. You must keep intact all notices that refer to the Applicable License and to the disclaimer of warranties with every copy of the Work as included in the Adaptation You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Adaptation, You may not impose any effective technological measures on the Adaptation that restrict the ability of a recipient of the Adaptation from You to exercise the rights granted to that recipient under the terms of the Applicable License. This Section 4(b) applies to the Adaptation as incorporated in a Collection, but this does not require the Collection apart from the Adaptation itself to be made subject to the terms of the Applicable License.
|
||||
You may not exercise any of the rights granted to You in Section 3 above in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. The exchange of the Work for other copyrighted works by means of digital file-sharing or otherwise shall not be considered to be intended for or directed toward commercial advantage or private monetary compensation, provided there is no payment of any monetary compensation in con-nection with the exchange of copyrighted works.
|
||||
If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and, (iv) consistent with Section 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4(d) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties.
|
||||
For the avoidance of doubt:
|
||||
|
||||
Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License;
|
||||
Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License if Your exercise of such rights is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(c) and otherwise waives the right to collect royalties through any statutory or compulsory licensing scheme; and,
|
||||
Voluntary License Schemes. The Licensor reserves the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License that is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(c).
|
||||
Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise.
|
||||
5. Representations, Warranties and Disclaimer
|
||||
|
||||
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING AND TO THE FULLEST EXTENT PERMITTED BY APPLICABLE LAW, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO THIS EXCLUSION MAY NOT APPLY TO YOU.
|
||||
|
||||
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
7. Termination
|
||||
|
||||
This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Adaptations or Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
|
||||
Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.
|
||||
8. Miscellaneous
|
||||
|
||||
Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
|
||||
Each time You Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License.
|
||||
If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
|
||||
No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
|
||||
This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.
|
||||
The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law.
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
# Freenove ESP32-S3-WROOM CAM
|
||||
|
||||
In progress
|
||||
|
||||
<img src="Board.jpg" width=50% height=50%>
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
## Freenove_ESP32_S3_WROOM_Board
|
||||
|
||||
A kit with a Freenove® ESP32-S3 Board for learning programming and electronics.
|
||||
|
||||
<img src='Board.jpg' width='70%'/>
|
||||
|
||||
ESP32-S3 chip is manufactured by Espressif®.
|
||||
>Espressif® is a trademark of Espressif Systems (Shanghai) Co.Ltd (https://www.espressif.com/).
|
||||
|
||||
Freenove ESP32-S3 Board can be uploaded code using Arduino® IDE.
|
||||
> Arduino® is a trademark of Arduino LLC (https://www.arduino.cc/).
|
||||
|
||||
<img src='ESP32S3_Pinout.png' width='100%'/>
|
||||
|
||||
### Download
|
||||
|
||||
Click the green "Code" button, then click "Download ZIP" button in the pop-up window.
|
||||
Do NOT click the "Open in Desktop" button, it will lead you to install Github software.
|
||||
|
||||
> If you meet any difficulties, please contact our technical team for help.
|
||||
|
||||
### Use
|
||||
|
||||
1. Download the ZIP file as above.
|
||||
2. Unzip it and you will get a folder contains tutorials and related files.
|
||||
3. Please start with "Start Here.pdf".
|
||||
|
||||
### Support
|
||||
|
||||
Freenove provides free and quick customer support. Including but not limited to:
|
||||
|
||||
* Quality problems of products
|
||||
* Problems of products when used
|
||||
* Questions of learning and creation
|
||||
* Opinions and suggestions
|
||||
* Ideas and thoughts
|
||||
|
||||
Please send an email to:
|
||||
|
||||
[support@freenove.com](mailto:support@freenove.com)
|
||||
|
||||
We will reply within one working day.
|
||||
|
||||
### Purchase
|
||||
|
||||
Please visit the following page to purchase our products:
|
||||
|
||||
http://freenove.com/store
|
||||
|
||||
Business customers please contact us through the following email address:
|
||||
|
||||
[sale@freenove.com](mailto:sale@freenove.com)
|
||||
|
||||
### About
|
||||
|
||||
Freenove provides open source electronic products and services.
|
||||
|
||||
Freenove is committed to helping customers learn programming and electronic knowledge, quickly implement product prototypes, realize their creativity and launch innovative products. Our services include:
|
||||
|
||||
* Kits for learning programming and electronics
|
||||
* Kits compatible with Arduino®, Raspberry Pi®, micro:bit®, etc.
|
||||
* Kits for robots, smart cars, drones, etc.
|
||||
* Components, modules and tools
|
||||
* Design and customization
|
||||
|
||||
To learn more about us or get our latest information, please visit our website:
|
||||
|
||||
http://www.freenove.com
|
||||
|
||||
### Copyright
|
||||
|
||||
All the files in this repository are released under [Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-nc-sa/3.0/).
|
||||
You can find a copy of the license in this repository.
|
||||
|
||||

|
||||
|
||||
> It means you can use these files on your own derived works, in part or completely. But not for commercial use.
|
||||
|
||||
Freenove® brand and logo are trademarks of Freenove Creative Technology Co., Ltd. Must not be used without permission.
|
||||
|
||||
Other registered trademarks and their owners appearing in this repository:
|
||||
|
||||
Arduino® is a trademark of Arduino LLC (https://www.arduino.cc/).
|
||||
Raspberry Pi® is a trademark of Raspberry Pi Foundation (https://www.raspberrypi.org/).
|
||||
micro:bit® is a trademark of Micro:bit Educational Foundation (https://www.microbit.org/).
|
||||
Espressif® is a trademark of Espressif Systems (Shanghai) Co.Ltd (https://www.espressif.com/).
|
||||
Binary file not shown.
Loading…
Reference in New Issue