i got this error from serial monitor:
23:02:13.274 -> E (7156) cam_hal: cam_dma_config(300): frame buffer malloc failed
23:02:13.321 -> E (7156) cam_hal: cam_config(384): cam_dma_config failed
23:02:13.321 -> E (7156) camera: Camera config failed with error 0xffffffff
23:02:13.321 -> Camera init failed with error 0xffffffffE (217) psram: PSRAM ID read error: 0x52c3606d
can anyone solve my problem? This my full code:
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include "esp_camera.h"
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Isi dengan alamat dan password wifi kalian
const char* ssid = "Awan";
const char* password = "__o8z3__";
String BOTtoken = "6986562297:AAFp-ujtEgNaSWB_GeQhlY5A9VGuJoTuWmc"; // Isi dengan token dari botfather tele
String chatId = "6465172692"; // Isi dengan id chat dari id bot
bool sendPhoto = false;
WiFiClientSecure clientTCP;
UniversalTelegramBot bot(BOTtoken, clientTCP);
// Camera settings
#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
//#define FLASHpin 4
//bool flashState = LOW;
bool adaGerakan = false;
int botRequestDelay = 1000; // Setiap 1 detik akan check bot
long lastTimeBotRan;
#define SDA_PIN 0
#define SCL_PIN 16
// Knock sensor settings
const int knockSensor = 12;
const int programSwitch = 15;
const int Solenoid = 14;
const int greenLED = 4;
const int threshold = 100;
const int rejectValue = 25;
const int averageRejectValue = 15;
const int knockFadeTime = 150;
const int lockTurnTime = 5000; //waktu yang diperlukan solenoid untuk terbuka
const int maximumKnocks = 20;
const int knockComplete = 1200;
int secretCode[maximumKnocks] = {25, 25, 35, 50, 40, 50, 0, 0, 0, 0};
int knockReadings[maximumKnocks];
int knockSensorValue = 0;
int programButtonPressed = false;
int buzzerDoor = 2;
// LCD settings
LiquidCrystal_I2C lcd(0x27, 16, 2);
const String label1 = "Pintu terkunci";
const String label2 = "Initialize...";
const String label3 = "Silahkan masuk";
const String label4 = "Merekam";
const String label5 = "Program Siap";
const String label6 = "Silahkan Ketuk";
const String label7 = "Ketukan tersimpan";
void handleNewMessages(int numNewMessages);
String sendPhotoTelegram();
static void IRAM_ATTR detectsMovement(void * arg){
adaGerakan = true;
}
void setup(){
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
Serial.begin(115200);
Serial.println("mulai program");
digitalWrite(greenLED, HIGH);
//pinMode(FLASHpin, OUTPUT);
//digitalWrite(FLASHpin, flashState);
pinMode(Solenoid, OUTPUT);
pinMode(greenLED, OUTPUT);
pinMode(buzzerDoor, OUTPUT);
pinMode(programSwitch, INPUT);
Wire.begin(SDA_PIN, SCL_PIN);
lcd.begin(16, 2);
lcd.setCursor(0,1);
lcd.backlight();
clearLCDLine(0);
lcd.print(label2);
delay(2000);
clearLCDLine(0);
lcd.print(label5);
delay(1000);
clearLCDLine(0);
lcd.print(label6);
clearLCDLine(1);
lcd.print(label1);
// Setup WiFi connection
WiFi.mode(WIFI_STA);
Serial.println();
Serial.print("Menghubungkan wifi: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
clientTCP.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println();
Serial.println("WiFi connected");
Serial.print("ESP32-CAM IP Address: ");
Serial.println(WiFi.localIP());
// Camera initialization
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_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;
//init with high specs to pre-allocate larger buffers
if(psramFound()){
config.frame_size = FRAMESIZE_UXGA;
config.jpeg_quality = 10; //0-63 lower number means higher quality
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12; //0-63 lower number means higher quality
config.fb_count = 1;
}
// Camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
delay(1000);
ESP.restart();
}
// Drop down frame size for higher initial frame rate
sensor_t * s = esp_camera_sensor_get();
s->set_framesize(s, FRAMESIZE_CIF); // UXGA|SXGA|XGA|SVGA|VGA|CIF|QVGA|HQVGA|QQVGA
// PIR Motion Sensor mode INPUT_PULLUP
//err = gpio_install_isr_service(0);
err = gpio_isr_handler_add(GPIO_NUM_13, &detectsMovement, (void *) 13); // pin sensor yg di gunakan
if (err != ESP_OK){
Serial.printf("Handler add failed with error 0x%x \r\n", err);
}
err = gpio_set_intr_type(GPIO_NUM_13, GPIO_INTR_POSEDGE);
if (err != ESP_OK){
Serial.printf("Set intr type failed with error 0x%x \r\n", err);
}
}
void loop(){
if (sendPhoto){
Serial.println("Persiapan foto");
sendPhotoTelegram();
sendPhoto = false;
}
if(adaGerakan){
bot.sendMessage(chatId, "ADA GERAKAN !!!", "");
Serial.println("Ada gerakan");
sendPhotoTelegram();
adaGerakan = false;
}
if (millis() > lastTimeBotRan + botRequestDelay){
int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
while (numNewMessages){
Serial.println("Got response");
handleNewMessages(numNewMessages);
numNewMessages = bot.getUpdates(bot.last_message_received + 1);
}
lastTimeBotRan = millis();
}
// Knock sensor part
knockSensorValue = analogRead(knockSensor);
if (digitalRead(programSwitch)==HIGH){
programButtonPressed = true;
clearLCDLine(1);
lcd.print("Recording");
Serial.println("Recording");
} else {
programButtonPressed = false;
clearLCDLine(1);
lcd.print("Pintu Terkunci");
Serial.println("Pintu Terkunci");
}
if (knockSensorValue >=threshold){
listenToSecretKnock();
}
}
void listenToSecretKnock(){
clearLCDLine(1);
lcd.print("Silahkan Ketuk Pintu");
Serial.println("Silahkan ketuk pintu");
int i = 0;
for (i=0;i<maximumKnocks;i++){
knockReadings[i]=0;
}
int currentKnockNumber=0;
int startTime=millis();
int now=millis();
digitalWrite(greenLED, LOW);
if (programButtonPressed==true){
}
delay(knockFadeTime);
digitalWrite(greenLED, HIGH);
if (programButtonPressed==true){
digitalWrite(buzzerDoor, HIGH);
tone(buzzerDoor, 1000);
}
do {
knockSensorValue = analogRead(knockSensor);
if (knockSensorValue >=threshold){
clearLCDLine(1);
lcd.print("Mengetuk");
Serial.println("Mengetuk");
now=millis();
knockReadings[currentKnockNumber] = now-startTime;
currentKnockNumber ++;
startTime=now;
digitalWrite(greenLED, LOW);
if (programButtonPressed==true){
}
delay(knockFadeTime);
digitalWrite(greenLED, HIGH);
if (programButtonPressed==true){
digitalWrite(buzzerDoor, HIGH);
tone(buzzerDoor, 1000);
}
}
now=millis();
} while ((now-startTime < knockComplete) && (currentKnockNumber < maximumKnocks));
if (programButtonPressed==false){
if (validateKnock() == true){
triggerDoorUnlock();
} else {
clearLCDLine(1);
lcd.print("Ketukan salah");
Serial.println("Ketukan salah");
digitalWrite(greenLED, LOW);
for (i=0;i<4;i++){
digitalWrite(buzzerDoor, HIGH);
tone(buzzerDoor, 1000);
delay(100);
digitalWrite(buzzerDoor, LOW);
noTone(buzzerDoor);
delay(100);
}
clearLCDLine(1);
digitalWrite(greenLED, HIGH);
}
} else {
validateKnock();
clearLCDLine(0);
lcd.print("Silahkan ketuk");
clearLCDLine(1);
lcd.print("Ketukan tersimpan");
lcd.print("Ketukan tersimpan");
delay(1000);
clearLCDLine(1);
lcd.print("Pintu terkunci");
lcd.print("Pintu terkunci");
Serial.println("Ketukan baru");
digitalWrite(greenLED, HIGH);
for (i=0;i<3;i++){
delay(50);
digitalWrite(buzzerDoor, HIGH);
tone(buzzerDoor, 1000);
digitalWrite(greenLED, LOW);
delay(100);
digitalWrite(buzzerDoor, LOW);
noTone(buzzerDoor);
digitalWrite(greenLED, HIGH);
}
}
}
void triggerDoorUnlock(){
clearLCDLine(1);
lcd.print("Silahkan masuk");
Serial.println("Silahkan masuk");
int i=0;
digitalWrite(Solenoid, HIGH);
delay (lockTurnTime);
digitalWrite(Solenoid, LOW);
for (i=0; i < 5; i++){
digitalWrite(greenLED, LOW);
delay(100);
digitalWrite(greenLED, HIGH);
delay(100);
}
clearLCDLine(1);
lcd.print("Pintu terkunci");
Serial.println("Pintu terkunci");
}
boolean validateKnock(){
int i=0;
int currentKnockCount = 0;
int secretKnockCount = 0;
int maxKnockInterval = 0;
for (i=0;i<maximumKnocks;i++){
if (knockReadings[i] > 0){
currentKnockCount++;
}
if (secretCode[i] > 0){
secretKnockCount++;
}
if (knockReadings[i] > maxKnockInterval){
maxKnockInterval = knockReadings[i];
}
}
if (programButtonPressed==true){
for (i=0;i<maximumKnocks;i++){
secretCode[i]= map(knockReadings[i],0, maxKnockInterval, 0, 50);
}
digitalWrite(greenLED, LOW);
delay(1000);
digitalWrite(greenLED, HIGH);
delay(50);
for (i = 0; i < maximumKnocks ; i++){
digitalWrite(greenLED, LOW);
if (secretCode[i] > 0){
delay( map(secretCode[i],0, 50, 0, maxKnockInterval));
digitalWrite(greenLED, HIGH);
}
delay(50);
}
return false;
}
if (currentKnockCount != secretKnockCount){
return false;
}
int totaltimeDifferences=0;
int timeDiff=0;
for (i=0;i<maximumKnocks;i++){
knockReadings[i]= map(knockReadings[i],0, maxKnockInterval, 0, 50);
timeDiff = abs(knockReadings[i]-secretCode[i]);
if (timeDiff > rejectValue){
return false;
}
totaltimeDifferences += timeDiff;
}
if (totaltimeDifferences/secretKnockCount>averageRejectValue){
return false;
}
return true;
}
void handleNewMessages(int numNewMessages){
Serial.print("Handle New Messages: ");
Serial.println(numNewMessages);
for (int i = 0; i < numNewMessages; i++){
// Chat id of the requester
String chat_id = String(bot.messages[i].chat_id);
if (chat_id != chatId){
bot.sendMessage(chat_id, "Unauthorized user", "");
continue;
}
// Print the received message
String text = bot.messages[i].text;
Serial.println(text);
String fromName = bot.messages[i].from_name;
//if (text == "/flash") {
//flashState = !flashState;
//digitalWrite(FLASHpin, flashState);
//}
if (text == "/foto") {
sendPhoto = true;
Serial.println("New photo request");
}
if (text == "/start"){
String welcome = "at-mo production\n";
welcome += "klik tulisan biru\n";
welcome += "/foto : untuk ambil gambar langsung\n";
// welcome += "/flash : untuk on off lampu flash\n";
welcome += "system ini otomatis kirim foto saat terjadi gerakan.\n";
bot.sendMessage(chatId, welcome, "Markdown");
}
}
}
String sendPhotoTelegram(){
const char* myDomain = "api.telegram.org";
String getAll = "";
String getBody = "";
camera_fb_t * fb = NULL;
fb = esp_camera_fb_get();
if(!fb) {
Serial.println("kamera gagal ambil gambar");
delay(1000);
ESP.restart();
return "Camera capture failed";
}
Serial.println("Connect to " + String(myDomain));
// Serial.println("Camera Captured");
if (clientTCP.connect(myDomain, 443)){
Serial.println("Connection to telegram server ready");
Serial.println("berhasil terhubung");
String head = "--RandomNerdTutorials\r\nContent-Disposition: form-data; name=\"chat_id\";\r\n\r\n" + chatId + "\r\n--RandomNerdTutorials\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
String tail = "\r\n--RandomNerdTutorials--\r\n";
uint16_t imageLen = fb->len;
uint16_t extraLen = head.length() + tail.length();
uint16_t totalLen = imageLen + extraLen;
clientTCP.println("POST /bot" + BOTtoken + "/sendPhoto HTTP/1.1");
clientTCP.println("Host: " + String(myDomain));
clientTCP.println("Content-Length: " + String(totalLen));
clientTCP.println("Content-Type: multipart/form-data; boundary=RandomNerdTutorials");
clientTCP.println();
clientTCP.print(head);
uint8_t *fbBuf = fb->buf;
size_t fbLen = fb->len;
for (size_t n=0;n<fbLen;n=n+1024) {
if (n+1024<fbLen) {
clientTCP.write(fbBuf, 1024);
fbBuf += 1024;
}
else if (fbLen%1024>0) {
size_t remainder = fbLen%1024;
clientTCP.write(fbBuf, remainder);
}
}
clientTCP.print(tail);
esp_camera_fb_return(fb);
int waitTime = 10000; // Give up to 10 seconds to send the image
long startTimer = millis();
boolean state = false;
while ((startTimer + waitTime) > millis()){
Serial.print(".");
delay(100); // Wait for a reply from the server
while (clientTCP.available()){
char c = clientTCP.read();
if (c == '\0') Serial.print("");
if (c != '\r' && c != '\n') getBody += String(c);
if (getBody.startsWith("{\"ok\":true")){
state = true;
Serial.println("state true");
}
if (state == true && c == '}'){
Serial.println("break");
break;
}
}
if (state == true){
break;
}
}
if (state == true){
Serial.println("Done!");
getAll = "Photo sent successfully!";
}
else{
Serial.println("Failed to send photo");
getAll = "Picture failure!";
}
}
else{
Serial.println("Connection to " + String(myDomain) + " failed");
getAll = "Connection failed";
}
getBody = "";
clientTCP.stop();
Serial.println("Telegram response :");
Serial.println(getAll);
return getAll;
}
void clearLCDLine(int line){
for(int n = 0; n < 20; n++) { // 20 indicates symbols in line. For 2x16 LCD write - 16
lcd.setCursor(n,line);
lcd.print(" ");
}
lcd.setCursor(0,line); // set cursor in the beginning of deleted line
}