How to use ov24640 camera withaout PSRAM

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
}

If you dont have PSRAM, then you have to take smaller resolutinon picures.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.