Init fork from Stuart Robinson's repo

This commit is contained in:
2024-10-03 14:30:13 +03:00
commit 9395706524
201 changed files with 45709 additions and 0 deletions

View File

@@ -0,0 +1,447 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 19/03/22
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*********
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-cam-take-photo-save-microsd-card
Github repository at https://github.com/RuiSantosdotme/ESP32-CAM-Arduino-IDE
IMPORTANT!!!
- Select Board "AI Thinker ESP32-CAM"
- GPIO 0 must be connected to GND to upload a sketch
- After connecting GPIO 0 to GND, press the ESP32-CAM on-board RESET button to put your board in flashing mode
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*********/
/*******************************************************************************************************
Program Operation - This is a program using the ESP32CAM to take pictures and transmit those pictures via
LoRa radio to another remote Arduino.
This program is for an ESP32CAM board that has an SPI LoRa module set up on the following pins; NSS 12,
NRESET 14, SCK 4, MISO 13, MOSI 2, RFBUSY 15, 3.3V VCC and GND. All other pins on the SX128X are not
connected.
Note that the white LED on pin 4 or the transistor controlling it need to be removed so that the LoRa
device can properly use pin 4.
The program wakes up, takes a picture and starts the transfer of the picture (from its memory array in
PSRAM) with LoRa, more details of the file transfer process will be found here;
https://stuartsprojects.github.io/2021/09/20/Large-Data-Transfers-with-LoRa-Part3.html
Note that if the camera fails then the program will attempt to send, and wait for the acknowledge, for a
DTinfo packet reporting the fail.
Serial monitor baud rate is set at 115200
*******************************************************************************************************/
#define USELORA //enable this define to use LoRa packets
//#define USEFLRC //enable this define to use FLRC packets
#include <Arduino.h>
#include "FS.h" //SD Card ESP32
#include "SD_MMC.h" //SD Card ESP32
#include "soc/soc.h" //disable brownout problems
#include "soc/rtc_cntl_reg.h" //disable brownout problems
#include "driver/rtc_io.h"
#include <SPI.h>
#include <SX128XLT.h> //get library here > https://github.com/StuartsProjects/SX12XX-LoRa
#include <ProgramLT_Definitions.h>
#include "Settings.h" //LoRa and program settings
SX128XLT LoRa; //create a library class instance called LoRa, needed for ARtransferIRQ.h
#define ENABLEMONITOR //enable define to see progress messages in ARtransferIRQ.h
#define PRINTSEGMENTNUM //enable to print segment numbers as transfer progresses
#define ENABLEARRAYCRC //enable this define to use and show CRCs
//#define DISABLEPAYLOADCRC //enable this define if you want to not use packet payload CRC checking
//#define DEBUG //enable this define to show data transfer debug info
RTC_DATA_ATTR int16_t bootCount = 0; //variables to save in RTC ram
RTC_DATA_ATTR uint16_t sleepcount = 0;
RTC_DATA_ATTR uint16_t pictureNumber = 0; //number of picture taken, set to 0 on reset
#include "esp_camera.h"
camera_config_t config; //stores the camera configuration parameters
#include <ARtransferIRQ.h> //library of array transfer functions
bool SDOK;
void loop()
{
SDOK = false;
ARDTflags = 0;
if (initMicroSDCard()) //need to setup SD card before camera
{
Serial.println(F("SD Card OK"));
SDOK = true;
}
else
{
Serial.println(F("****************************"));
Serial.println(F("ERROR - SD Card Mount Failed"));
Serial.println(F("****************************"));
bitSet(ARDTflags, ARNoFileSave);
}
if (!configInitCamera())
{
bitSet(ARDTflags, ARNoCamera); //set flag bit for no camera working
Serial.println(F("Camera config failed"));
Serial.println(F("Sending DTInfo packet"));
setupLoRaDevice();
ARsendDTInfo();
startSleep();
}
else
{
if (takePhotoSend(PicturesToTake, PictureDelaymS))
{
//picture taken OK
startSleep();
}
else
{
//picture take failed
Serial.println("********************************");
Serial.println("ERROR - Take picture send failed");
Serial.println("********************************");
Serial.println();
Serial.println("Sending DTInfo packet");
Serial.flush();
bitSet(ARDTflags, ARNoCamera); //set flag bit for no camera working
setupLoRaDevice();
ARsendDTInfo();
startSleep();
}
}
startSleep();
}
void startSleep()
{
LoRa.setSleep(CONFIGURATION_RETENTION);
rtc_gpio_hold_en(GPIO_NUM_4);
rtc_gpio_hold_en(GPIO_NUM_12); //hold LoRa device off in sleep
esp_sleep_enable_timer_wakeup(SleepTimesecs * uS_TO_S_FACTOR);
Serial.print(F("Start Sleep "));
Serial.print(SleepTimesecs);
Serial.println(F("s"));
Serial.flush();
sleepcount++;
esp_deep_sleep_start();
Serial.println("This should never be printed !!!");
}
bool initMicroSDCard()
{
if (!SD_MMC.begin("/sdcard", true)) //use this line for 1 bit mode, pin 2 only, 4,12,13 not used
{
return false;
}
uint8_t cardType = SD_MMC.cardType();
if (cardType == CARD_NONE)
{
Serial.println(F("Unknown SD card type"));
return false;
}
return true;
}
void redFlash(uint16_t flashes, uint16_t ondelaymS, uint16_t offdelaymS)
{
uint16_t index;
pinMode(REDLED, OUTPUT); //setup pin as output
for (index = 1; index <= flashes; index++)
{
digitalWrite(REDLED, LOW);
delay(ondelaymS);
digitalWrite(REDLED, HIGH);
delay(offdelaymS);
}
pinMode(REDLED, INPUT); //setup pin as input
}
bool setupLoRaDevice()
{
SPI.begin(SCK, MISO, MOSI, NSS);
if (LoRa.begin(NSS, NRESET, RFBUSY, LORA_DEVICE))
{
Serial.println(F("LoRa device found"));
}
else
{
Serial.println(F("LoRa Device error"));
return false;
}
#ifdef USELORA
LoRa.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate);
Monitorport.println(F("Using LoRa packets"));
#endif
#ifdef USEFLRC
LoRa.setupFLRC(Frequency, Offset, BandwidthBitRate, CodingRate, BT, Syncword);
Monitorport.println(F("Using FLRC packets"));
#endif
Serial.println();
return true;
}
void setup()
{
redFlash(4, 125, 125);
//WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
rtc_gpio_hold_dis(GPIO_NUM_4);
rtc_gpio_hold_dis(GPIO_NUM_12); //LoRa NSS back to normal control after sleep
pinMode(2, INPUT_PULLUP);
digitalWrite(NSS, HIGH);
pinMode(NSS, OUTPUT);
Serial.begin(115200);
Serial.println();
Serial.println(F(__FILE__));
if (bootCount == 0) //run this only the first time after programming or power up
{
bootCount = bootCount + 1;
}
Serial.println(F("Awake !"));
Serial.print(F("Bootcount "));
Serial.println(bootCount);
Serial.print(F("Sleepcount "));
Serial.println(sleepcount);
#ifdef DISABLEPAYLOADCRC
LoRa.setReliableConfig(NoReliableCRC);
#endif
if (LoRa.getReliableConfig(NoReliableCRC))
{
Serial.println(F("Payload CRC disabled"));
}
else
{
Serial.println(F("Payload CRC enabled"));
}
}
//***********************************************************************************************
// Start camera Code
//***********************************************************************************************
bool configInitCamera()
{
Serial.println(F("Initialising the camera module "));
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_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG; //YUV422,GRAYSCALE,RGB565,JPEG
//Select lower framesize if the camera doesn't support PSRAM
if (psramFound())
{
Serial.println(F("PSRAM found"));
config.frame_size = FRAMESIZE_SVGA; //FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA, XUGA == 100K+, SVGA = 25K+
config.jpeg_quality = 10; //10-63 lower number means higher quality
config.fb_count = 2;
}
else
{
Serial.println(F("No PSRAM"));
config.frame_size = FRAMESIZE_XGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}
esp_err_t err = esp_camera_init(&config); //Initialize the Camera
if (err != ESP_OK)
{
Serial.printf("Camera init failed with error 0x%x", err);
Serial.println();
return false;
}
sensor_t * s = esp_camera_sensor_get();
s->set_brightness(s, 0); // -2 to 2
s->set_contrast(s, 0); // -2 to 2
s->set_saturation(s, 0); // -2 to 2
s->set_special_effect(s, 0); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
s->set_whitebal(s, 1); // 0 = disable , 1 = enable
s->set_awb_gain(s, 1); // 0 = disable , 1 = enable
s->set_wb_mode(s, 1); // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
s->set_exposure_ctrl(s, 1); // 0 = disable , 1 = enable
s->set_aec2(s, 1); // 0 = disable , 1 = enable
s->set_ae_level(s, 0); // -2 to 2
s->set_aec_value(s, 450); // 0 to 1200
s->set_gain_ctrl(s, 1); // 0 = disable , 1 = enable
s->set_agc_gain(s, 0); // 0 to 30
s->set_gainceiling(s, (gainceiling_t)0); // 0 to 6
s->set_bpc(s, 1); // 0 = disable , 1 = enable
s->set_wpc(s, 0); // 0 = disable , 1 = enable
s->set_raw_gma(s, 1); // 0 = disable , 1 = enable
s->set_lenc(s, 0); // 0 = disable , 1 = enable
s->set_hmirror(s, 0); // 0 = disable , 1 = enable
s->set_vflip(s, 0); // 0 = disable , 1 = enable
s->set_dcw(s, 1); // 0 = disable , 1 = enable
s->set_colorbar(s, 0); // 0 = disable , 1 = enable
return true;
}
uint16_t takePhotoSend(uint8_t num, uint32_t gapmS)
{
uint8_t index = 1;
char filenamearray[32];
bool sentOK = false;
String path;
camera_fb_t * fb = esp_camera_fb_get();
for (index = 1; index <= num; index++) //take a number of pictures, send last
{
pictureNumber++;
path = "/pic" + String(pictureNumber) + ".jpg";
Serial.print("Next picture file name ");
Serial.println(path.c_str());
if (!fb)
{
Serial.println(F("*****************************"));
Serial.println(F("ERROR - Camera capture failed"));
Serial.println(F("*****************************"));
delay(1000);
pictureNumber--; //restore picture number
bitSet(ARDTflags, ARNoFileSave);
}
Serial.println(F("Camera capture success"));
#ifdef DEBUG
Serial.print(F("First 8 bytes "));
printarrayHEX(fb->buf, 0, 8);
Serial.println();
Serial.print(F("Last 8 bytes "));
printarrayHEX(fb->buf, (fb->len - 8), 8);
Serial.println();
#endif
if (SDOK)
{
Serial.println(F("Save picture to SD card"));
fs::FS &fs = SD_MMC; //save picture to microSD card
File file = fs.open(path.c_str(), FILE_WRITE);
if (!file)
{
Serial.println(F("*********************************************"));
Serial.println(F("ERROR Failed to open SD file in writing mode"));
Serial.println(F("*********************************************"));
bitSet(ARDTflags, ARNoFileSave);
}
else
{
file.write(fb->buf, fb->len); // payload (image), payload length
Serial.printf("Saved file to path: %s\r\n", path.c_str());
}
file.close();
}
else
{
Serial.println(F("***************"));
Serial.println(F("No SD available"));
Serial.println(F("***************"));
}
}
SD_MMC.end();
if (setupLoRaDevice())
{
Serial.print(F("Send with LoRa "));
Serial.println(path.c_str());
uint8_t tempsize = path.length();
path.toCharArray(filenamearray, tempsize + 1); //copy file name to the local filenamearray
filenamearray[tempsize + 1] = 0; //ensure there is a null at end of filename in filenamearray
sentOK = ARsendArray(fb->buf, fb->len, filenamearray, tempsize + 1); //pass array pointer and length across to LoRa send function
}
else
{
Serial.println(F("LoRa device not available"));
}
esp_camera_fb_return(fb); //return the frame buffer back to the driver for reuse
delay(gapmS);
if (sentOK)
{
Serial.print(filenamearray);
Serial.println(F(" Sent OK"));
return pictureNumber;
}
else
{
Serial.print(filenamearray);
Serial.println(F(" Send picture failed"));
}
return 0;
}
void printarrayHEX(uint8_t *buff, uint32_t startaddr, uint32_t len)
{
uint32_t index;
uint8_t buffdata;
for (index = startaddr; index < (startaddr + len); index++)
{
buffdata = buff[index];
if (buffdata < 16)
{
Serial.print(F("0"));
}
Serial.print(buffdata, HEX);
Serial.print(F(" "));
}
}

View File

@@ -0,0 +1,92 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 19/03/22
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
//updated pinouts for 'ESP32CAM_Long_Range_Wireless_Adapter PCB dated 271121
//Note transistor driving the White LED on pin 4, or the LED needs to be removed
#define NSS 12 //select on LoRa device
#define NRESET 14 //reset pin on LoRa device
#define RFBUSY 15 //busy pin on LoRa device
#define SCK 4 //SCK on SPI3
#define MISO 13 //MISO on SPI3
#define MOSI 2 //MOSI on SPI3
#define REDLED 33 //pin number for ESP32CAM on board red LED, set logic level low for on
#define LORA_DEVICE DEVICE_SX1280 //this is the device we are using
const uint32_t Frequency = 2445000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const int8_t TXpower = 10; //LoRa transmit power
//******* Setup LoRa modem parameters here ! ***************
const uint8_t Bandwidth = LORA_BW_1600; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF5; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
//******* Setup FLRC modem parameters here ! ***************
const uint8_t BandwidthBitRate = FLRC_BR_1_300_BW_1_2; //FLRC bandwidth and bit rate, 1.3Mbs
//const uint8_t BandwidthBitRate = FLRC_BR_0_260_BW_0_3; //FLRC 260kbps
const uint8_t CodingRate = FLRC_CR_1_0; //FLRC coding rate
const uint8_t BT = RADIO_MOD_SHAPING_BT_1_0; //FLRC BT
const uint32_t Syncword = 0x01234567; //FLRC uses syncword
const uint32_t TXtimeoutmS = 5000; //mS to wait for TX to complete
const uint32_t RXtimeoutmS = 60000; //mS to wait for receiving a packet
const uint32_t ACKdelaymS = 0; //ms delay after packet actioned and ack sent
const uint32_t ACKdelaystartendmS = 25; //ms delay before ack sent at array start wrie and end write
const uint32_t ACKsegtimeoutmS = 75; //mS to wait for receiving an ACK before re-trying transmit segment
const uint32_t ACKopentimeoutmS = 500; //mS to wait for receiving an ACK before re-trying transmit file open
const uint32_t ACKclosetimeoutmS = 500; //mS to wait for receiving an ACK before re-trying transmit file close
const uint32_t DuplicatedelaymS = 25; //ms delay if there has been an duplicate segment or command receipt
const uint32_t NoAckCountLimit = 250; //if no NoAckCount exceeds this value - restart transfer
const uint32_t FunctionDelaymS = 0; //delay between functions such as open file, send segments etc
const uint32_t PacketDelaymS = 1000; //mS delay between transmitted packets such as DTInfo etc
const uint8_t DTSegmentSize = 245; //number of bytes in each segment or payload
const uint8_t ARDTfilenamesize = 32; //size of filename buffer
const uint8_t StartAttempts = 2; //number of attempts to start transfer before a fail
const uint8_t SendAttempts = 5; //number of attempts carrying out a process before a restart
const uint8_t HeaderSizeMax = 12; //max size of header in bytes, minimum size is 7 bytes
const uint8_t DataSizeMax = 245; //max size of data array in bytes
const uint16_t NetworkID = 0x3210; //a unique identifier to go out with packet
const uint16_t SleepTimesecs = 15; //sleep time in seconds after each TX loop
const uint32_t uS_TO_S_FACTOR = 1000000; //Conversion factor for micro seconds to seconds
const uint8_t PicturesToTake = 1; //number of pictures to take at each wakeup, only last is sent via LoRa
const uint32_t PictureDelaymS = 1000; //delay in mS between pictures
#ifdef USELORA
const uint8_t SegmentSize = 245; //number of bytes in each segment, 245 is maximum value for LoRa
#endif
#ifdef USEFLRC
const uint8_t SegmentSize = 117; //number of bytes in each segment, 117 is maximum value for FLRC
#endif
// Pin definition for CAMERA_MODEL_AI_THINKER
// Change pin definition if you're using another ESP32 with camera module
#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