Hi there,
The main workflow is to generate a random filename, use the EloquentEsp32cam Library to take images (3 to get around an issue with the cam module in which the first image taken has a green tint), save it to the microSD Card and then use the SX128XLT library to send it via LoRa.
These are the Pin Definitions in the Settings.h file.
#define NSS 12
#define RFBUSY 14
#define NRESET 3
#define DIO1 13
#define DIO2 -1 //not used
#define DIO3 -1 //not used
#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used
#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used
This is the main.cpp, with the main pin configs beeing:
#define SD_CS 1
#define SCK 15
#define MISO 33
#define MOSI 32
#include <Arduino.h>
#define USELORA
#include <eloquent_esp32cam.h>
#include <eloquent_esp32cam/viz/mjpeg.h>
#include <WiFi.h>
#include <vector>
#include <cstdint>
#include <SPI.h>
#include <SD.h>
#include <SX128XLT.h>
#include <ProgramLT_Definitions.h>
#include "Settings.h"
using namespace eloq;
using namespace eloq::viz;
using eloq::camera;
unsigned long lastPictureTime = 0;
const long pictureInterval = 30000;
String currentFileName = "";
#define SD_CS 1
#define SCK 15
#define MISO 33
#define MOSI 32
SX128XLT LoRa; //create an SX128XLT library instance called LoRa, required by SDtransfer.h
//#define ENABLEMONITOR //enable monitor prints
#define PRINTSEGMENTNUM //enable this define to print segment numbers
#define ENABLEFILECRC //enable this define to uses and show file CRCs
//#define DISABLEPAYLOADCRC //enable this define if you want to disable payload CRC checking
//#define DEBUG //see additional debug info
#define SDLIB //define SDLIB for SD.h or SDFATLIB for SDfat.h
//#define SDFATLIB
#include <DTSDlibrary.h> //library of SD functions
#include <SDtransfer.h>
bool transmitting = false;
void useBuzzer() {
// try to reuse a already used PIN like the SD_CS or MISO
SPI.end(); // End SD card communication
pinMode(MISO, OUTPUT);
tone(MISO, 2000, 200);
delay(250);
noTone(MISO);
tone(MISO, 2000, 200);
delay(250);
noTone(MISO);
tone(MISO, 2000, 200);
delay(250);
noTone(MISO);
delay(1000);
ESP.restart();
}
void setRandomFileName() {
// Define the characters that can be part of the random string
const String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
String randomString = "";
// Initialize random seed
randomSeed(esp_random());
// always generate a 8 length random string as SD library can handle 8 length file names ( plus the.jpg)
for (size_t i = 0; i < 8; i++) {
// Pick a random character from chars
int index = random(chars.length()); // random() returns a number from 0 to chars.length()-1
randomString += chars[index];
}
currentFileName = "/"+randomString+".jpg";
}
// take in filename, take 3 pictures, save the latest to sd card
void takeAndStorePicture() {
//Serial.println("taking first image");
if (!camera.capture().isOk()) {
//Serial.println(camera.exception.toString());
return;
}
delay(1000);
//Serial.println("taking second image");
if (!camera.capture().isOk()) {
//.println(camera.exception.toString());
return;
}
delay(1000);
//Serial.println("taking third image");
if (!camera.capture().isOk()) {
//Serial.println(camera.exception.toString());
return;
}
uint32_t imageSize = camera.getSizeInBytes(); // Get the size of the image in bytes
uint8_t* imageBuffer = camera.frame -> buf;
// Create a new file on the SD card with filename currentFileName and use the imageBuffer
File imgFile = SD.open(currentFileName, FILE_WRITE); // Open the file in write mode
if (!imgFile) {
//Serial.println("Failed to open file for writing");
return;
}
imgFile.write(imageBuffer, imageSize); // Write the image buffer to file
imgFile.close(); // Close the file after writing
//Serial.println("Image saved to SD card.");
}
// send the just taken and saved image from sd card via lora
void initTransmitOfSavedFile() {
transmitting = true;
#ifdef ENABLEMONITOR
Monitorport.println(F("Transfer started"));
#endif
uint32_t filelength;
// Allocate a modifiable array
char FileName[currentFileName.length() + 1];
strcpy(FileName, currentFileName.c_str());
filelength = SDsendFile(FileName, currentFileName.length());
if (filelength)
{
transmitting = false;
#ifdef ENABLEMONITOR
Monitorport.println(F("Transfer finished"));
#endif
}
else
{
transmitting = false;
#ifdef ENABLEMONITOR
Monitorport.println(F("Transfer failed"));
Monitorport.println();
#endif
}
}
void setup() {
#ifdef ENABLEMONITOR
Monitorport.begin(115200);
Monitorport.println();
Monitorport.println(F(__FILE__));
Monitorport.flush();
#endif
SPI.begin(SCK,MISO,MOSI);
if (LoRa.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
}
else
{
#ifdef ENABLEMONITOR
Monitorport.println(F("LoRa device error"));
#endif
while (1)
{
//flash
}
}
#ifdef USELORA
LoRa.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate);
//Serial.println(F("Using LoRa packets"));
#endif
#ifdef USEFLRC
LoRa.setupFLRC(Frequency, Offset, BandwidthBitRate, CodingRate, BT, Syncword);
Serial.println(F("Using FLRC packets"));
#endif
#ifdef ENABLEMONITOR
Monitorport.println();
Monitorport.print(F("Initializing SD card..."));
#endif
if (DTSD_initSD(SD_CS))
{
#ifdef ENABLEMONITOR
Monitorport.println(F("SD Card initialized."));
#endif
}
else
{
//Monitorport.println(F("SD Card failed, or not present."));
while (1) ; //led_Flash(100, 25);
}
#ifdef ENABLEMONITOR
Monitorport.println();
#endif
#ifdef DISABLEPAYLOADCRC
LoRa.setReliableConfig(NoReliableCRC);
#endif
if (LoRa.getReliableConfig(NoReliableCRC))
{
#ifdef ENABLEMONITOR
Monitorport.println(F("Payload CRC disabled"));
#endif
}
else
{
#ifdef ENABLEMONITOR
Monitorport.println(F("Payload CRC enabled"));
#endif
}
SDDTFileTransferComplete = false;
#ifdef ENABLEMONITOR
Monitorport.println(F("SDfile transfer ready"));
Monitorport.println();
#endif
//Serial.println("LoRa and SD setup complete");
//Setup Camera
delay(2000);
camera.pinout.wrover();
camera.brownout.disable();
camera.resolution.hd();
camera.quality.high();
// init camera
while (!camera.begin().isOk())
delay(100);
//Serial.println(camera.exception.toString());
//Serial.println("Camera OK");
}
void loop() {
unsigned long currentTime = millis();
// Check if it's time to take and store a new picture
if (currentTime - lastPictureTime > pictureInterval && !transmitting) {
//Serial.println("Start Image Taking, Saving and Transmitting");
lastPictureTime = currentTime; // Update lastPictureTime to current time
// Set a new random file name
setRandomFileName();
delay(250);
// Take a picture and store it
takeAndStorePicture();
delay(250);
// Initialize transmission of the saved file
// hier noch durch ein Timeout ergänzen so dass die Kamera durchgestartet wird, wenn der Transfer fehl schlägt
initTransmitOfSavedFile();
//useBuzzer();
}
}