Merge branch 'pico-camera-read-input-cw' into pico-v0.11

pico-v0.11
alanbjohnston 3 years ago committed by GitHub
commit 382d59163d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -39,17 +39,23 @@
#include <ctype.h> #include <ctype.h>
// Pico GPIO pin assignments // Pico GPIO pin assignments
#define LPF_PIN 8 // LPF is installed #define PI_TX 0 // Serial to Pi transmit data
#define PI_3V3_PIN 9 // 3.3V supply used to detect Pi Zero #define PI_RX 1 // Serial to Pi receive data
#define SDA 2 // I2C 1 Data
#define SCL 3 // I2C 1 Clock
#define SDA2 4 // I2C 2 Data
#define SCL2 5 // I2C 2 Clock
#define BPSK_CONTROL_A 6 // was 16 // control for Phase A to switch
#define BPSK_CONTROL_B 7 // was 15 // control for Phase A to switch
#define TX2 8 // Serial2 to ESP32-CAM transmit data
#define RX2 9 // Serial2 to ESP32-CAM receive data
#define MAIN_PB_PIN 10 // Main board PB pushbutton pin #define MAIN_PB_PIN 10 // Main board PB pushbutton pin
#define TXC_PIN 11 // Transceiver Board is present #define TXC_PIN 11 // Transceiver Board is present
#define SWTX_PIN 16 // was 14 SR_FRS_05W Transmit Pico software serial port #define LPF_PIN 12 // BPF is installed
//#define SQUELCH 15 // SR_FRS_05W Squelch out #define PI_3V3_PIN 13 // 3.3V supply used to detect Pi Zero
//#define MAIN_INA219 16 // Power the INA219s on the Main board
#define BPSK_PWM_A_PIN 14 // was 6 // PWM Output Phase A to switch #define BPSK_PWM_A_PIN 14 // was 6 // PWM Output Phase A to switch
#define BPSK_PWM_B_PIN 15 // was 7 // PWM Output Phase B to switch #define BPSK_PWM_B_PIN 15 // was 7 // PWM Output Phase B to switch
#define BPSK_CONTROL_A 6 // was 16 // control for Phase A to switch #define SWTX_PIN 16 // was 14 SR_FRS_05W Transmit Pico software serial port
#define BPSK_CONTROL_B 7 // was 15 // control for Phase A to switch
#define PTT_PIN 17 // SR_FRS_05W PTT Push to Talk - transmit #define PTT_PIN 17 // SR_FRS_05W PTT Push to Talk - transmit
#define STEM_LED_GREEN 18 // STEM board LED1 Green #define STEM_LED_GREEN 18 // STEM board LED1 Green
#define STEM_LED_BLUE 19 // STEM board LED2 Blue #define STEM_LED_BLUE 19 // STEM board LED2 Blue
@ -98,6 +104,18 @@
#define OFF - 1 #define OFF - 1
#define ON 1 #define ON 1
#define PROMPT_CALLSIGN 1
#define PROMPT_SIM 2
#define PROMPT_LAT 3
#define PROMPT_RESET 4
#define PROMPT_QUERY 5
#define PROMPT_HELP 6
#define PROMPT_RESTART 7
volatile int prompt = false;
char serial_string[128];
//#define WAV_DATA_LENGTH (50000 * 8) //#define WAV_DATA_LENGTH (50000 * 8)
uint32_t tx_freq_hz = 434900000 + FREQUENCY_OFFSET; uint32_t tx_freq_hz = 434900000 + FREQUENCY_OFFSET;
@ -123,7 +141,7 @@ void write_little_endian(unsigned int word, int num_bytes, FILE *wav_file);
static int init_rf(); static int init_rf();
void test_radio(); void test_radio();
void config_radio(); void config_radio();
void send_packet(); void send_aprs_packet();
void read_ina219(); void read_ina219();
void read_sensors(); void read_sensors();
void get_tlm_ao7(); void get_tlm_ao7();
@ -160,6 +178,10 @@ void transmit_char(char character);
void transmit_string(char *string); void transmit_string(char *string);
void transmit_callsign(char *callsign); void transmit_callsign(char *callsign);
void parse_payload(); void parse_payload();
void load_files();
void show_dir();
void serial_input();
void get_serial_string();
#ifndef STASSID #ifndef STASSID
#define STASSID "Pico" #define STASSID "Pico"
@ -270,6 +292,7 @@ float Sensor2 = 0;
void eeprom_word_write(int addr, int val); void eeprom_word_write(int addr, int val);
short eeprom_word_read(int addr); short eeprom_word_read(int addr);
int first_time = true; int first_time = true;
int first_time_sstv = true;
int first_read = true; int first_read = true;
float T2 = 27; // Temperature data point 1 float T2 = 27; // Temperature data point 1
float R2 = 170; // Reading data point 1 float R2 = 170; // Reading data point 1
@ -303,6 +326,8 @@ bool cw_stop = false;
int pb_state = RELEASED; int pb_state = RELEASED;
int mode_count = 0; int mode_count = 0;
unsigned long pb_press_start; unsigned long pb_press_start;
const char sstv1_filename[] = "/sstv_image_1_320_x_240.jpg";
const char sstv2_filename[] = "/sstv_image_2_320_x_240.jpg";
bool TimerHandler0(struct repeating_timer *t); bool TimerHandler0(struct repeating_timer *t);
RPI_PICO_Timer ITimer0(0); RPI_PICO_Timer ITimer0(0);

@ -12,7 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -39,6 +38,11 @@
#include "hardware/gpio.h" #include "hardware/gpio.h"
#include "hardware/adc.h" #include "hardware/adc.h"
#include "SSTV-Arduino-Scottie1-Library.h" #include "SSTV-Arduino-Scottie1-Library.h"
#include "LittleFS.h"
// jpg files to be stored in flash storage on Pico (FS 512kB setting)
#include "sstv1.h"
#include "sstv2.h"
Adafruit_INA219 ina219_1_0x40; Adafruit_INA219 ina219_1_0x40;
Adafruit_INA219 ina219_1_0x41(0x41); Adafruit_INA219 ina219_1_0x41(0x41);
@ -63,7 +67,7 @@ void setup() {
new_mode = mode; new_mode = mode;
Serial.begin(9600); Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT); pinMode(LED_BUILTIN, OUTPUT);
blinkTimes(1); blinkTimes(1);
@ -82,8 +86,9 @@ void setup() {
// if Pi is present, run Payload OK software // if Pi is present, run Payload OK software
// otherwise, run CubeSatSim Pico code // otherwise, run CubeSatSim Pico code
Serial.println("\n\nCubeSatSim Pico v0.1 starting...\n\n"); Serial.println("\n\nCubeSatSim Pico v0.13 starting...\n\n");
load_files();
/* /*
pinMode(PI_3V3_PIN, INPUT); pinMode(PI_3V3_PIN, INPUT);
Serial.print("Pi 3.3V: "); Serial.print("Pi 3.3V: ");
@ -111,19 +116,20 @@ void setup() {
start_ina219(); start_ina219();
if (i2c_bus3 == false) if (i2c_bus3 == false)
config_simulated_telem(); config_simulated_telem();
config_telem(); config_telem();
// setup radio depending on mode // setup radio depending on mode
config_radio(); config_radio();
/* /*
if (check_for_wifi()) { if (check_for_wifi()) {
wifi = true; wifi = true;
configure_wifi(); configure_wifi();
} }
*/ */
start_button_isr(); // start_button_isr();
setup_sstv(); setup_sstv();
start_isr(); start_isr();
start_pwm(); start_pwm();
@ -136,6 +142,8 @@ void setup() {
sleep(5.0); sleep(5.0);
/**/ /**/
start_button_isr();
sampleTime = (unsigned int) millis(); sampleTime = (unsigned int) millis();
ready = TRUE; // flag for core1 to start looping ready = TRUE; // flag for core1 to start looping
@ -165,14 +173,45 @@ void loop() {
else if ((mode == AFSK) || (mode == CW)) { else if ((mode == AFSK) || (mode == CW)) {
get_tlm_ao7(); get_tlm_ao7();
if (mode == AFSK) { if (mode == AFSK) {
send_packet(); send_aprs_packet();
} else if (mode == CW) { } else if (mode == CW) {
send_cw(); send_cw();
} }
} }
else if (mode == SSTV) { else if (mode == SSTV)
Serial.println("\nSending SSTV image!"); {
send_sstv("/cam.raw"); char image_file[128];
if (first_time_sstv) {
strcpy(image_file, sstv1_filename);
first_time_sstv = false;
} else {
// get jpeg from camera in future
strcpy(image_file, sstv2_filename);
}
Serial.print("\nSending SSTV image ");
print_string(image_file);
// send_sstv("/cam.raw");
// send_sstv(image_file);
char output_file[] = "/cam.bin";
jpeg_decode(image_file, output_file);
Serial.println("Start transmit!!!");
digitalWrite(PTT_PIN, LOW); // start transmit
digitalWrite(MAIN_LED_BLUE, HIGH);
scottie1_transmit_file(output_file);
Serial.println("Stop transmit!");
digitalWrite(PTT_PIN, HIGH); // stop transmit
digitalWrite(MAIN_LED_BLUE, LOW);
Serial.println("\nImage sent!"); Serial.println("\nImage sent!");
} }
else else
@ -210,13 +249,22 @@ void loop() {
config_telem(); config_telem();
config_radio(); config_radio();
} }
if (prompt) {
Serial.println("Need to prompt for input!");
prompt_for_input();
prompt = false;
}
// Calculate loop time // Calculate loop time
Serial.print("\nLoop time: "); Serial.print("\nLoop time: ");
Serial.println(millis() - startSleep); Serial.println(millis() - startSleep);
} }
bool TimerHandler1(struct repeating_timer *t) { bool TimerHandler1(struct repeating_timer *t) {
serial_input();
// check for button press // check for button press
if (digitalRead(MAIN_PB_PIN) == PRESSED) // pushbutton is pressed if (digitalRead(MAIN_PB_PIN) == PRESSED) // pushbutton is pressed
process_pushbutton(); process_pushbutton();
@ -225,8 +273,8 @@ bool TimerHandler1(struct repeating_timer *t) {
if (wifi) if (wifi)
check_for_browser(); check_for_browser();
return(true); return(true);
} }
void read_reset_count() { void read_reset_count() {
@ -264,7 +312,10 @@ void read_reset_count() {
} }
} }
void send_packet() { void send_aprs_packet() {
// encode telemetry
get_tlm_ao7();
// digitalWrite(LED_BUILTIN, LOW); // digitalWrite(LED_BUILTIN, LOW);
char str[1000]; char str[1000];
@ -421,7 +472,7 @@ void config_telem() {
set_pin(AUDIO_OUT_PIN); set_pin(AUDIO_OUT_PIN);
char callsign[] = "W3ZM"; // char callsign[] = "W3ZM";
set_callsign(callsign); set_callsign(callsign);
char lat_default[] = "0610.55S"; char lat_default[] = "0610.55S";
char lon_default[] = "10649.62E"; char lon_default[] = "10649.62E";
@ -1933,6 +1984,8 @@ void config_radio()
mySerial.println("AT+DMOSETGROUP=0,432.2510,432.2510,0,8,0,0\r"); mySerial.println("AT+DMOSETGROUP=0,432.2510,432.2510,0,8,0,0\r");
// sleep(0.5); // sleep(0.5);
// mySerial.println("AT+DMOSETMIC=6,0\r"); // mySerial.println("AT+DMOSETMIC=6,0\r");
if (mode == SSTV)
first_time_sstv = true;
} }
// } else if (mode == FSK) { // moved to below // } else if (mode == FSK) { // moved to below
@ -1943,7 +1996,7 @@ void config_radio()
transmit_on(); transmit_on();
} }
if ((mode == FSK) || (mode == SSTV)) if ((mode == FSK)) // || (mode == SSTV))
// start_isr(); // start_isr();
transmit_on(); transmit_on();
} }
@ -2924,9 +2977,9 @@ void sleep(float time) { // sleeps for intervals more than 0.1 seconds
} }
*/ */
void sleep(float time) { // sleeps for intervals more than 0.01 milli seconds void sleep(float timer) { // sleeps for intervals more than 0.01 milli seconds
unsigned long time_us = (unsigned long)(time * 1000000.0); unsigned long time_us = (unsigned long)(timer * 1000000.0);
unsigned long startSleep = micros(); unsigned long startSleep = micros();
while ((micros() - startSleep) < time_us) { while ((micros() - startSleep) < time_us) {
// busy_wait_us(100); // busy_wait_us(100);
@ -3454,7 +3507,8 @@ void transmit_cw(int freq, float duration) { // freq in Hz, duration in millise
while((micros() - start) < duration_us) { while((micros() - start) < duration_us) {
digitalWrite(AUDIO_OUT_PIN, phase); // ToDo: if no TXC, just turn on PWM carrier digitalWrite(AUDIO_OUT_PIN, phase); // ToDo: if no TXC, just turn on PWM carrier
phase = !phase; phase = !phase;
sleep(min(start + duration_us - micros(), period_us) / 1.0E6); float time_left = (float)(start + duration_us - micros());
sleep(min(time_left, period_us) / 1.0E6);
} }
digitalWrite(AUDIO_OUT_PIN, LOW); digitalWrite(AUDIO_OUT_PIN, LOW);
} }
@ -3539,3 +3593,247 @@ void parse_payload() {
} }
} }
} }
void show_dir() {
LittleFS.begin();
Dir dir = LittleFS.openDir("/");
// or Dir dir = LittleFS.openDir("/data");
Serial.println("FS directory:");
while (dir.next()) {
Serial.print(dir.fileName());
if(dir.fileSize()) {
File f = dir.openFile("r");
Serial.print(" ");
Serial.println(f.size());
}
}
Serial.println(">");
}
void load_files() {
LittleFS.begin();
File f;
f = LittleFS.open("sstv_image_1_320_x_240.jpg", "r");
if (f) {
Serial.println("Image sstv_image_1_320_x_240.jpg already in FS");
f.close();
} else {
Serial.println("Loading image sstv_image_1_320_x_240.jpg into FS");
f = LittleFS.open("sstv_image_1_320_x_240.jpg", "w+");
if (f.write(sstv_image_1_320_x_240, sizeof(sstv_image_1_320_x_240)) < sizeof(sstv_image_1_320_x_240)) {
Serial.println("Loading image failed. Is Flash Size (FS) set to 512kB?");
delay(2000);
}
f.close();
}
f = LittleFS.open("sstv_image_2_320_x_240.jpg", "r");
if (f) {
Serial.println("Image sstv_image_2_320_x_240.jpg already in FS");
f.close();
} else {
Serial.println("Loading image sstv_image_2_320_x_240.jpg into FS");
f = LittleFS.open("sstv_image_2_320_x_240.jpg", "w+");
if (f.write(sstv_image_2_320_x_240, sizeof(sstv_image_2_320_x_240)) < sizeof(sstv_image_2_320_x_240)) {
Serial.println("Loading image failed. Is Flash Size (FS) set to 512kB?");
delay(2000);
}
f.close();
}
show_dir();
}
void serial_input() {
if (prompt == false) { // only query if not in the middle of prompting
if (Serial.available() > 0) { // check for user input on serial port
// blink(50);
char result = Serial.read();
if ((result != '\n') && (result != '\r')) {
Serial.println(result);
switch(result) {
case 'h':
case 'H':
Serial.println("Help");
prompt = PROMPT_HELP;
/*
Serial.println("\nChange settings by typing the letter:");
Serial.println("h Help info");
Serial.println("a AFSK/APRS mode");
Serial.println("c CW mode");
Serial.println("f FSK/DUV mode");
Serial.println("b BPSK mode");
Serial.println("s SSTV mode");
Serial.println("i Restart");
Serial.println("c CALLSIGN");
Serial.println("t Simulated Telemetry");
Serial.println("r Resets Count, or payload & EEPROM");
Serial.println("l Lat and Long");
Serial.println("? Query sensors\n");
*/
break;
case 'a':
case 'A':
Serial.println("Change to AFSK/APRS mode");
new_mode = AFSK;
break;
case 'm':
case 'M':
Serial.println("Change to CW mode");
break;
case 'f':
case 'F':
Serial.println("Change to FSK/DUV mode");
break;
case 'b':
case 'B':
Serial.println("Change to BPSK mode");
new_mode = BPSK;
break;
case 's':
case 'S':
Serial.println("Change to SSTV mode");
new_mode = SSTV;
break;
case 'i':
case 'I':
Serial.println("Restart CubeSatsim software");
prompt = PROMPT_RESTART;
break;
case 'c':
case 'C':
Serial.println("Change the CALLSIGN");
prompt = PROMPT_CALLSIGN;
break;
case 't':
case 'T':
Serial.println("Change the Simulated Telemetry");
prompt = PROMPT_SIM;
break;
case 'r':
case 'R':
Serial.println("Change the Resets Count or Reset payload and stored EEPROM values");
prompt = PROMPT_RESET;
break;
case 'l':
case 'L':
Serial.println("Change the Latitude and Longitude");
prompt = PROMPT_LAT;
break;
case '?':
Serial.println("Query payload sensors");
prompt = PROMPT_QUERY;
break;
default:
Serial.println("Not a command\n");
break;
}
if (new_mode != mode)
transmit_off();
sleep(2.0);
}
}
}
}
void prompt_for_input() {
while (Serial.available() > 0) // clear any characters in serial input buffer
Serial.read();
switch(prompt) {
case PROMPT_HELP:
Serial.println("\nChange settings by typing the letter:");
Serial.println("h Help info");
Serial.println("a AFSK/APRS mode");
Serial.println("c CW mode");
Serial.println("f FSK/DUV mode");
Serial.println("b BPSK mode");
Serial.println("s SSTV mode");
Serial.println("i Restart");
Serial.println("c CALLSIGN");
Serial.println("t Simulated Telemetry");
Serial.println("r Resets Count, or payload & EEPROM");
Serial.println("l Lat and Long");
Serial.println("? Query sensors\n");
break;
case PROMPT_CALLSIGN:
Serial.println("Editing the CALLSIGN in the onfiguration file for CubeSatSim");
Serial.println("Return keeps current value.");
Serial.print("\nCurrent callsign is ");
Serial.println(callsign);
Serial.print("Enter callsign in all capitals: ");
get_serial_string();
print_string(serial_string);
if (strlen(serial_string) > 0) {
strcpy(callsign, serial_string);
Serial.println("Callsign updated!");
} else
Serial.println("Callsign not updated!");
break;
case PROMPT_SIM:
break;
case PROMPT_LAT:
break;
case PROMPT_QUERY:
break;
case PROMPT_RESET:
break;
case PROMPT_RESTART:
Serial.println("Restart not yet implemented");
break; }
}
void get_serial_string() {
int input = 0;
int i = 0;
unsigned int elapsed_time = (unsigned int) millis();
while ((input != '\n') && (input!= '\r') && (i < 128) && ((millis() - elapsed_time) < 20000)) {
if (Serial.available() > 0) {
input = Serial.read();
if ((input != '\n') && (input!= '\r')) {
serial_string[i++] = input;
Serial.write(input);
}
}
sleep(0.1);
}
serial_string[i] = 0;
Serial.println(" ");
}

@ -0,0 +1,463 @@
// ESP32-CAM JPEG over Serial
//
// by Jim McLaughlin and Alan Johnston
//
// Tested on ESP32-CAM-MB Camera Module hardware
// with Arduino 1.8.19 using Board: ESP32 Arduino Selected: AI Thinker ESP32-CAM
//
// example loop() program stores a JPEG and sends it over serial then waits 5 seconds.
//
// Based on code example https://github.com/espressif/arduino-esp32/tree/master/libraries/ESP32/examples/Camera/CameraWebServer
//
// initialize_camera initializes the ESP32-CAM - only call once per boot!
//
// save_camera_image takes a JPEG image and stores it with selected filename on
// built-in SPIFFS storage on ESP32-CAM (no SD card is needed)
//
// send_image_serial sends a selected filename from built-in storage over the serial
// port at 115200 in binary format with a 30 byte start flag and 40 byte end flag
// CRC-8 checksum is calculated over file and end flag and sent as the last byte.
//
// listDir gives a directory file listing of the built-in file storage
//
#include <Arduino.h>
#include "esp_camera.h"
#include <FastCRC.h>
#include "FS.h"
#include "SPIFFS.h"
// some info: https://visualgdb.com/tutorials/esp32/camera/
//#define DEBUG
#define FORMAT_SPIFFS_IF_FAILED true
void app_main();
void send_image_serial(char *filename);
void save_camera_image(char* filename);
void initialize_camera();
static esp_err_t init_camera();
#define RX2_pin IO16 // AMBE3000 RX to ESP32 TXD
#define TX2_pin IO17 // AMBE3000 TX to ESP32 RXD
#define LED_PIN 33 // LED pin on ESP32-CAM-MB board is 33
const char start_flag[] = "3d99de816e5ad7742b61a37c39141783"; // MD5 hash of "ESP32-CAM" as start flag
const char end_flag[] = "f681a5c52351befe0e3524eb1a40f14b7803317a"; // SHA-1 hash of "ESP32-CAM" as end flag
FastCRC8 CRC8;
char hexValue[6];
char file_buf[50000];
int file_len;
bool file_flag = false;
camera_fb_t *pic;
// example code from https://github.com/espressif/arduino-esp32/blob/master/libraries/LittleFS/examples/LITTLEFS_test/LITTLEFS_test.ino
//
void listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
Serial.printf("Listing directory: %s\r\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.name(), levels - 1);
}
} else {
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print("\tSIZE: ");
Serial.println(file.size());
}
file = root.openNextFile();
}
}
void deleteFile(fs::FS &fs, const char * path) {
Serial.printf("Deleting file: %s\r\n", path);
if (fs.remove(path)) {
Serial.println("- file deleted");
} else {
Serial.println("- delete failed");
}
}
void setup() {
delay(5000);
Serial.begin(112500);
initialize_camera();
Serial.println("ESP32-CAM Camera initialized");
pinMode(LED_PIN, OUTPUT); // Set the pin as output
// On the ESP32 you can also define another hardware serial interface using pins of your choice like this
// Serial2.begin(115200,SERIAL_8N1,14,15);
// Serial.println("Initializing CRC");
// crc.setPolynome(0x1021);
if (!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)) {
Serial.println("SPIFFS Mount Failed");
return;
}
listDir(SPIFFS, "/", 0);
}
void loop() {
char filename[] = "/cam.jpg";
save_camera_image(filename);
send_image_serial(filename);
delay(5000);
}
/**
This example takes a picture every 5s and print its size on serial monitor.
*/
// =============================== SETUP ======================================
// 1. Board setup (Uncomment):
// #define BOARD_WROVER_KIT
// #define BOARD_ESP32CAM_AITHINKER
/**
2. Kconfig setup
If you have a Kconfig file, copy the content from
https://github.com/espressif/esp32-camera/blob/master/Kconfig into it.
In case you haven't, copy and paste this Kconfig file inside the src directory.
This Kconfig file has definitions that allows more control over the camera and
how it will be initialized.
*/
/**
3. Enable PSRAM on sdkconfig:
CONFIG_ESP32_SPIRAM_SUPPORT=y
More info on
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html#config-esp32-spiram-support
*/
// ================================ CODE ======================================
//#include <esp_log.h>
//#include <esp_system.h>
//#include <nvs_flash.h>
//#include <sys/param.h>
//#include <string.h>
//#include "freertos/FreeRTOS.h"
//#include "freertos/task.h"
// ESP32Cam (AiThinker) PIN Map
#define CAM_PIN_PWDN 32
#define CAM_PIN_RESET -1 //software reset will be performed
#define CAM_PIN_XCLK 0
#define CAM_PIN_SIOD 26
#define CAM_PIN_SIOC 27
#define CAM_PIN_D7 35
#define CAM_PIN_D6 34
#define CAM_PIN_D5 39
#define CAM_PIN_D4 36
#define CAM_PIN_D3 21
#define CAM_PIN_D2 19
#define CAM_PIN_D1 18
#define CAM_PIN_D0 5
#define CAM_PIN_VSYNC 25
#define CAM_PIN_HREF 23
#define CAM_PIN_PCLK 22
//static const char *TAG = "example:take_picture";
static camera_config_t camera_config = {
.pin_pwdn = CAM_PIN_PWDN,
.pin_reset = CAM_PIN_RESET,
.pin_xclk = CAM_PIN_XCLK,
.pin_sscb_sda = CAM_PIN_SIOD,
.pin_sscb_scl = CAM_PIN_SIOC,
.pin_d7 = CAM_PIN_D7,
.pin_d6 = CAM_PIN_D6,
.pin_d5 = CAM_PIN_D5,
.pin_d4 = CAM_PIN_D4,
.pin_d3 = CAM_PIN_D3,
.pin_d2 = CAM_PIN_D2,
.pin_d1 = CAM_PIN_D1,
.pin_d0 = CAM_PIN_D0,
.pin_vsync = CAM_PIN_VSYNC,
.pin_href = CAM_PIN_HREF,
.pin_pclk = CAM_PIN_PCLK,
//XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental)
.xclk_freq_hz = 20000000,
.ledc_timer = LEDC_TIMER_0,
.ledc_channel = LEDC_CHANNEL_0,
.pixel_format = PIXFORMAT_JPEG, // Options: YUV422, GRAYSCALE, RGB565, JPEG
.frame_size = FRAMESIZE_QVGA, // Options: QQVGA-UXGA, QVGA Do not use sizes above QVGA when not JPEG
.jpeg_quality = 12, //0-63 lower number means higher quality
.fb_count = 1, //if more than one, i2s runs in continuous mode. Use only with JPEG
// .grab_mode = CAMERA_GRAB_WHEN_EMPTY,
};
static esp_err_t init_camera()
{
//initialize the camera
esp_err_t err = esp_camera_init(&camera_config);
if (err != ESP_OK)
{
// ESP_LOGE(TAG, "Camera Init Failed");
return err;
}
return ESP_OK;
}
void initialize_camera() {
if (ESP_OK != init_camera()) {
Serial.println("Failed to initialize camera!");
return;
}
}
void save_camera_image(char* filename)
{
Serial.print("Saving camera image to file: ");
Serial.println(filename);
Serial.println("\nBlink...");
digitalWrite(LED_PIN, LOW); // Turn on
delay (100); // Wait 0.1 sec
digitalWrite(LED_PIN, HIGH); // Turn off
Serial.println("\nTaking picture...\n");
pic = esp_camera_fb_get();
const char path[] = "/cam.jpg";
Serial.println("Writing image file"); //: %s\r\n", path);
// File file = SPIFFS.open(path, FILE_WRITE);
File file = SPIFFS.open(filename, FILE_WRITE);
if (!file) {
Serial.println("- failed to open file for writing");
return;
}
for (int k = 0; k < pic->len; k++) {
file.write(pic->buf[k]);
}
file.close();
Serial.println("Write complete");
listDir(SPIFFS, "/", 0);
}
void send_image_serial(char *filename)
{
Serial.println("Sending image over serial");
Serial.println("\nBlink twice");
digitalWrite(LED_PIN, LOW); // Turn on
delay (100); // Wait 0.1 sec
digitalWrite(LED_PIN, HIGH); // Turn off
delay(100); // Wait 0.1 sec
digitalWrite(LED_PIN, LOW); // Turn on
delay (100); // Wait 0.1 sec
digitalWrite(LED_PIN, HIGH); // Turn off
// read from file
const char path[] = "/cam.jpg";
Serial.println("Reading image file"); //: %s\r\n", path);
// File file = SPIFFS.open(path, FILE_READ);
File file = SPIFFS.open(filename, FILE_READ);
if (!file) {
Serial.println("Failed to open file for reading");
return;
}
int k = 0;
while (file.available()) {
// file.write(pic->buf[size]);
file_buf[k] = file.read();
k++;
}
file.close();
file_len = k;
Serial.print(file_len);
Serial.println(" bytes read from file.");
file_flag = true;
// }
// Sending image file
Serial.println("Start of binary data:");
// Serial.println("\nResetting CRC");
// crc.restart();
int j = 0;
// flag at start
for (int i = 0; i < strlen(start_flag); i++) {
sprintf(hexValue, "%02X", start_flag[i]);
// Serial.print(hexValue);
Serial.write(start_flag[i]);
// Serial.print(start_flag[i], HEX);
}
#ifdef DEBUG
#endif
char str[] = "ESP32-CAM";
if (file_flag == true) {
// Serial.println("******************* Sending stored file! ***************************\n");
for (j = 0; j < file_len; j++) {
/// for (int i = 0; i < 9; i++) {
uint8_t *data = (uint8_t *) &file_buf[j];
// crc.add(data[0]);
// crc.add(data[0]);
/// crc.add(str[i]);
#ifndef DEBUG
if (file_buf[j] != 0x66)
sprintf(hexValue, "%02X", file_buf[j]);
else
strcpy(hexValue, "66");
Serial.write(file_buf[j]);
// Serial.print(hexValue);
/// Serial.write(str[j]);
#endif
// Serial.print(pic->buf[j], HEX);
#ifdef DEBUG
// char hexValue[5];
sprintf(hexValue, "%02X", file_buf[j]);
Serial.print(hexValue);
#endif
// Serial.print(" ");
}
} else { // !file_flag - read from camera
for (j = 0; j < pic->len; j++) {
/// for (int i = 0; i < 9; i++) {
uint8_t *data = (uint8_t *) &pic->buf[j];
// crc.add(data[0]);
// crc.add(data[0]);
/// crc.add(str[i]);
file_buf[j] = pic->buf[j];
#ifndef DEBUG
sprintf(hexValue, "%02X", pic->buf[j]);
Serial.write(pic->buf[j]);
// Serial.print(hexValue);
/// Serial.write(str[j]);
#endif
// Serial.print(pic->buf[j], HEX);
#ifdef DEBUG
// char hexValue[5];
sprintf(hexValue, "%02X", pic->buf[j]);
Serial.print(hexValue);
#endif
// Serial.print(" ");
}
}
// Serial.print("j = ");
// Serial.println(j);
// flag at end
for (int i = 0; i < strlen(end_flag); i++) {
sprintf(hexValue, "%02X", end_flag[i]);
// Serial.print(hexValue);
file_buf[j++] = end_flag[i];
Serial.write(end_flag[i]);
// Serial.print(end_flag[i], HEX);
// if (file_flag) {
// file_buf[j++] = end_flag[i];
// } else {
// pic->buf[i++] = end_flag[j];
// }
}
uint8_t * data;
int index1;
data = (uint8_t *) &file_buf[0];
index1 = j;
// int calculated_crc = crc8(data, index1, 0x07, 0x0000, 0x0000, false, false);
int calculated_crc = CRC8.smbus(data, index1);
//#ifndef DEBUG
sprintf(hexValue, "%02X", calculated_crc);
Serial.write(calculated_crc);
// Serial.print(hexValue);
// Serial.write(0xff & calculated_crc);
//#endif
//#ifdef DEBUG
// sprintf(hexValue, "%04X", calculated_crc);
// Serial.print(hexValue);
// Serial.println("\n ");
//#endif
Serial.println("\nEnd of binary data.");
Serial.println("\nCRC cacluation data:");
Serial.println(file_buf[0], HEX);
Serial.println(file_buf[j - 1], HEX);
Serial.println(j);
Serial.print("\nCRC sent with image: ");
// char hexValue[6];
sprintf(hexValue, "%02X", calculated_crc);
Serial.print(hexValue);
Serial.println("\n");
/* remove hex print
for (int i = 0; i < pic->len; i++) {
// Serial.write(pic->buf[i]);
Serial.print(pic->buf[i], HEX);
// Serial.print(" ");
}
Serial.println(" ");
*/
// use pic->buf to access the image
ESP_LOGI(TAG, "Picture taken! Its size was: %zu bytes", pic->len);
// format of the captured picture will be stored in the format field of the
// structure returned by esp_camera_fb_get()
Serial.print("image size ");
if (file_flag)
Serial.println(file_len);
else {
Serial.println(pic->len);
// must free the memory allocated by esp_camera_fb_get()
esp_camera_fb_return(pic);
}
Serial.println("File sent!");
}

@ -0,0 +1,228 @@
#include <LittleFS.h>
#include <FastCRC.h>
bool finished = false;
char buffer[100001];
int index1 = 0;
char start_flag[] = "3d99de816e5ad7742b61a37c39141783";
char end_flag[] = "f681a5c52351befe0e3524eb1a40f14b7803317a";
int flag_count = 0;
int start_flag_detected = false;
int start_flag_complete = false;
int end_flag_detected = false;
int jpeg_start = 0;
FastCRC8 CRC8;
//#define DEBUG
#define PICOW true
int led_pin = LED_BUILTIN;
void setup() {
// put your setup code here, to run once:
if (PICOW)
led_pin = STEM_LED2_PIN;
Serial.begin(115200);
delay(5000);
pinMode(led_pin, OUTPUT);
digitalWrite(led_pin, LOW);
delay(500);
digitalWrite(led_pin, HIGH);
delay(500);
digitalWrite(led_pin, LOW);
delay(500);
digitalWrite(led_pin, HIGH);
delay(500);
if (PICOW)
digitalWrite(led_pin, LOW);
delay(2000);
Serial2.setRX(9);
delay(100);
Serial2.setTX(8);
delay(100);
Serial2.begin(115200);
Serial.println("Starting");
LittleFS.begin();
}
void show_dir() {
int count = 0;
Dir dir = LittleFS.openDir("/");
// or Dir dir = LittleFS.openDir("/data");
Serial.println(">");
while (dir.next()) {
count++;
Serial.print(count);
Serial.print(" ");
Serial.print(dir.fileName());
// if(dir.fileSize()) {
File f = dir.openFile("r");
Serial.print(" ");
Serial.println(f.size());
// } else
// Serial.println(" ");
}
Serial.println(">");
}
void write_jpg() {
/*
Serial.println("---------------");
Serial.println(buffer[jpeg_start], HEX);
Serial.println(buffer[jpeg_start + 1], HEX);
Serial.println(buffer[jpeg_start + 2], HEX);
Serial.println(buffer[jpeg_start + 3], HEX);
*/
if ((buffer[jpeg_start] == 0xff) && (buffer[jpeg_start + 1] == 0xd8)
&& (buffer[index1 - 2] == 0xff) && (buffer[index1 - 1] == 0xd9)) {
Serial.println("Received a JPEG! Writing to file.");
File i = LittleFS.open("/cam.jpg", "w+");
if (i) {
i.write(&buffer[jpeg_start], (size_t) (index1 - jpeg_start));
finished = true;
} else
Serial.println("Error opening cam.jpg");
// Serial.println("---------------");
i.close();
// }
} else
Serial.println("Not a JPEG");
show_dir();
/*
delay(2000);
char read_values[2];
File i = LittleFS.open("/cam.jpg", "r");
while (i.available()) {
i.readBytes(read_values, 1);
char hexValue[5];
sprintf(hexValue, "%02X", read_values[0]);
Serial.print(hexValue);
}
i.close();
Serial.println("\n\n finished read");
*/
}
void loop() {
char input_file[] = "/cam.jpg";
char output_file[] = "/cam.bin";
get_image_file();
Serial.println("Got image from ESP-32-CAM!");
delay(1000);
}
void get_image_file() {
finished = false;
while (!finished) {
// put your main code here, to run repeatedly:
if (Serial2.available()) { // If anything comes in Serial2
byte octet = Serial2.read();
if (start_flag_complete) {
// Serial.println("Start flag complete detected");
buffer[index1++] = octet;
if (octet == end_flag[flag_count]) { // looking for end flag
// if (end_flag_detected) {
flag_count++;
// Serial.println("Found part of end flag!");
if (flag_count >= strlen(end_flag)) { // complete image
/// buffer[index1++] = octet;
Serial.println("\nFound end flag");
// Serial.println(octet, HEX);
while(!Serial2.available()) { } // Wait for another byte
// octet = Serial2.read();
// buffer[index1++] = octet;
// Serial.println(octet, HEX);
// while(!Serial2.available()) { } // Wait for another byte
int received_crc = Serial2.read();
// buffer[index1++] = octet;
Serial.print("\nFile length: ");
Serial.println(index1 - (int)strlen(end_flag));
// index1 -= 1; // 40;
// Serial.println(buffer[index1 - 1], HEX);
// int received_crc = buffer[index1];
// index1 -= 1;
uint8_t * data = (uint8_t *) &buffer[0];
#ifdef DEBUG
Serial.println("\nCRC cacluation data:");
Serial.println(buffer[0], HEX);
Serial.println(buffer[index1 - 1], HEX);
Serial.println(index1);
Serial.println(received_crc, HEX);
#endif
int calculated_crc = CRC8.smbus(data, index1);
// Serial.println(calculated_crc, HEX);
if (received_crc == calculated_crc)
Serial.println("CRC check succeeded!");
else
Serial.println("CRC check failed!");
index1 -= 40;
write_jpg();
index1 = 0;
start_flag_complete = false;
start_flag_detected = false; // get ready for next image
end_flag_detected = false;
flag_count = 0;
// delay(6000);
}
} else {
flag_count = 0;
}
/// buffer[index1++] = octet;
#ifdef DEBUG
char hexValue[5];
if (octet != 0x66) {
sprintf(hexValue, "%02X", octet);
Serial.print(hexValue);
} else {
// Serial.println("\n********************************************* Got a 66!");
Serial.print("66");
}
// Serial.write(octet);
#endif
if (index1 > 100000)
index1 = 0;
// }
} else if (octet == start_flag[flag_count]) { // looking for start flag
start_flag_detected = true;
flag_count++;
// Serial.println("Found part of start flag! ");
if (flag_count >= strlen(start_flag)) {
flag_count = 0;
start_flag_complete = true;
Serial.println("Found start flag!\n");
}
} else { // not the flag, keep looking
start_flag_detected = false;
flag_count = 0;
// Serial.println("Resetting. Not start flag.");
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save

Powered by TurnKey Linux.