Overeenkomst
3Dprinter camera met filament sensor.
Ik was al een tijdje bezig met een 3D printer camera, zodat ik makkelijk kon zien dat het printen ging zoals ik het wenste. Nadat ik mijn eerste camera gemonteerd had kwam ik achter beperkingen. Het lampje op de ESPcam gaf te weinig licht om in het donker, duidelijke foto's te kunnen zien.
Als snel had ik gemerkt dat streaming video veel internet verkeer veroorzaakte en het net zo duidelijk was of de printer goed werk leverde, met om de 5 seconden genomen foto's. Wel was duidelijk dat er een tijd en datum bij de foto afbeelding moest komen. Als er een netwerk probleem was moest je niet naar oude foto's kijken en denken dat ze actueel zijn.

Eerst had ik een apparte ledlamp gemonteerd bij de ESPcam. De ledlamp had een eigen voeding en moest appart bediend worden. De 3Dprinter waar de camera op gericht stond heeft een filment controller waardoor ik in eerste instantie die stap voor een filamentcontroller bij de ESPcam niet maakte.
Nadat mijn printer een paar keer een verstopping had merkte ik de noodzaak van een filament beweging controller.
Dus.... in de gele omlijsting de ESP32 cam, in de blauwe omlijstijsting de extra ledlamp en in de groene omlijsting de filament beweging controller.

Op Thingiverse keek ik voor een filament controller maar kon ik niet slagen voor wat ik zocht. Uiteindelijk heb ik zelf wat getekend.
Nu is het mogelijk voor de ESP32Cam om te kijken of de rol filament beweegt. Omdat de rol hoog staat en op kogellagers, wordt als er door de printer, (extruder) filament getrokken wordt, steeds iets meer door de rol geleverd. De rol zal dus nu niet heen en weer gaan.

Met een verlichting van een paar ledjes gaat de foto kwaliteit niet omhoog. Ik had eerst een ledstrip geplakt op een zelf getekend PLA strip maar dat geeft veel te donkere foto's.
vervolgens kwam ik op Aliexpres platte 12V leds tegen met een hoop licht. Daar heb ik er eerst 2 op een PLA strip geplakt, maar de lijm werd door de warmte weer vloeibaar. Uit eindelijk lukte het wel maar de andere versie heb ik op een strip aluminium geplakt.
De ledbalk wordt geschakeld via een ULN2003 door de ESP32Cam.
Dat gaf nog eerst wat problemen omdat ik een 500 mAmp adapter had en bij het inschakelen van de ledbalk, zakte de ingangspanning van 14V naar 4V wat de ESP32cam niet leuk vond.
Vervolgens een oude 1 Amp bel trafo uit de rommelbak gevist, die voorzien van een gelijkrichter en een lading elco's. Uiteraard meteen een huisje ontworpen en geprint voor de condensatoren en gelijk richters.

Eerste nederlaag was toch vermoedelijk het inschakelen van de extra verlichting via de ULN2003. Gezamelijke 12V en gezamelijke min los gekoppeld, hielp al wat. Het voorkwam (denk ik) piek rimpeling in de voeding.

Ook hoopte ik door de leds met PWM aan te sturen van half vermogen naar vol vermogen, piek spanningen weg te werken.
Hier merkte ik dat analogWrite() bij ESP32 niet werkt. Via mijn trouwe hulp randomnerds (zie bronnen) leerde ik over de LEDC werking.

Om een led te dimmen:
1) kies een PWM channel 0-15, is gewoon 1 van de 16 mogelijke leds die je onafhankelijk wil dimmen. Voor setup: const int ledChannel = 0
2) kies de frequentie voor het PWM signaal. Voor een led is 5000 (5KHz) Hz prima. Voor setup: const int freq = 5000
3) kies het signaal werk resolutie, keuze uit 1 t/m 16 bits. We kiezen 8 bits, dimbaar vanaf 0 t/m 255. Voor setup const int resolution = 8
4) maak een setup, in setup: ledcSetup(ledChannel, freq, resolution)
5) kies welke GPIO je wil aansturen, gebruiken om te dimmen. We kiezen GPIO 4, in setup ledcAttachPin(GPIO, channel) channel is dan bij 1 opgegeven.
6) nog even in setup of loop aangeven tussen 0 en 255 hoe fel de led moet branden: int dutycycle = 100 Of verander gewoon het woord dutycycle in een getal tussen 0 en 255.
7) eindelijk gaan we in loop, de led aansturen met ledcWrite(channel, dutycycle)

GPIO 4 en de witte led zijn aan elkaar verbonden waardoor de externe leds via een ULN2003 aangestuurd konden worden. Fritzing schema, de gele draad.
De zwarte draad komt van de lichtsluis bij de filament rol. GPIO2 De witte draad is + 3V3 voor de IR sluis.
Links van de 12V aanvoer draden zit bij mij de beltrafo die wisselstroom aanlevert. Via een connector gaat die 12V naar een DC/DC 5V omzetter voor de ESP32. Voor de omzetter gaat er een 12V aftakking naar de ULN2003 voor de ledbalk.

Vermoedelijk moet ik nog een condensator plaatsen want, aangesloten op de beltrafo stopt de ESP na 10 minuten met foto's zenden.
Eerst de externe LEDlichtbalk losgekoppeld van GPIO4 en gekoppeld aan GPIO13.
Omdat ik vermoede dat de ULN2003 open bleef staan schreef ik een sketch waarin alleen GPIO4 (interne witte led) en GPIO13 (aangesloten externe led) aangestuurd werden. Dat werkte perfect. De ULN met externe LEDlichtbalk deed wat er van hen verwacht werd.

Als ik een gewone ledstrip aansluit i.p.v. de speciale leds (op het Youtube filmpje, rechts), werkt ook alles zoals het hoort.
De combinatie foto maken en speciale LEDbalk licht aan geeft dus het probleem.

Vermoedelijk blijkt het vermogen van mijn trafo niet voldoende om de speciale extra ledbalk en foto nemen, tegelijk te doen.
Nu doe ik de ledverlichting in de sketch 1 regel eerder uit dan de de foto genomen wordt. Dat lijkt te werken.

Volgende stap is de filamentcontroller die naar GPIO2 moet.

#include <Arduino.h>
#include <WiFi.h>
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include "esp_camera.h"

const char* ssid = "netwerknaam";
const char* password = "netwerkwachtwoord";
String serverName = "websitewaarhetheenmoet";
String serverPath = "/paginawaarhetheenmoet.php";
int conn;
const int serverPort = 80;

WiFiClient client;

// CAMERA_MODEL_AI_THINKER
#define lampen 13
#define filmlamp 4
#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

const int timerInterval = 30000; // ca 3 sec. between each HTTP POST image
unsigned long vorigeMillis = 0; // last time image was sent

// setting PWM properties
const int freq = 5000;
const int ledChannel = 0;
const int resolutie = 8;

//---------------------------
void setup() {
Serial.begin(115200);
pinMode (filmlamp, OUTPUT); //Specify that LED pin is output
pinMode (lampen, OUTPUT); //Specify that LED pin is output
wifisetup();
camerasetup();
Serial.println("Setup klaar, eerste foto nu versturen.");
//digitalWrite (lampen,100);
digitalWrite (filmlamp,HIGH);
delay(500);
sendPhoto();
digitalWrite (filmlamp,LOW);
digitalWrite (lampen,0);
}
//-----------------------------
void loop()
{
unsigned long currentMillis = millis();
unsigned long tijd= currentMillis - vorigeMillis;

if (tijd >= (timerInterval-1500))
{
// lampen eerder aan zodat alles goed verlicht is
digitalWrite (lampen,255);
}
if (tijd >= timerInterval)
{
Serial.println("foto tijd");
sendPhoto();
vorigeMillis=currentMillis;
}
digitalWrite (lampen,0);
}
//-----------------
String sendPhoto()
{
String getAll;
String getBody;
digitalWrite(lampen,0);//Lampen uit i.v.m. spanning val
camera_fb_t * fb = NULL;
fb = esp_camera_fb_get(); //fb is dus foto
if(!fb)
{
Serial.println("Geen foto kunnen nemen.");
delay(1000);
ESP.restart();
}

Serial.println("Verbinden met server: " + serverName);

if (client.connect(serverName.c_str(), serverPort))
{
Serial.println("Verbonden met site.");
String head = "--RandomNerdTutorials\r\nContent-Disposition: form-data; name=\"imageFile\"; filename=\"Creality_3V2.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
String tail = "\r\n--RandomNerdTutorials--\r\n";

uint32_t imageLen = fb->len;
uint32_t extraLen = head.length() + tail.length();
uint32_t totalLen = imageLen + extraLen;

client.println("POST " + serverPath + " HTTP/1.1");
client.println("Host: " + serverName);
client.println("Content-Length: " + String(totalLen));
client.println("Content-Type: multipart/form-data; boundary=RandomNerdTutorials");
client.println();
client.print(head);

uint8_t *fbBuf = fb->buf;
size_t fbLen = fb->len;
Serial.println("Foto oversturen in stukjes van 1024 bytes");
int lampteller;
for (size_t n=0; <fbLen; n=n+1024)
{
if (lampteller==0){digitalWrite(filmlamp,HIGH);Serial.println(lampteller);}
if (lampteller>=10){digitalWrite(filmlamp,LOW);lampteller=0;}
lampteller++;
//if (n+1024 < fbLen){Serial.println("Foto oversturen in stukjes.");}
if (n+1024 < fbLen)
{
client.write(fbBuf, 1024);
fbBuf += 1024;
}
else if (fbLen%1024>0)
{

size_t remainder = fbLen%1024;
client.write(fbBuf, remainder);
}
}
client.print(tail);
Serial.println("Alles verzonden.");
esp_camera_fb_return(fb);

int timoutTimer = 10000;
long startTimer = millis();
boolean state = false;
int teller=0;
while ((startTimer + timoutTimer) > millis())
{
Serial.print(".");
teller++;
if (teller>500){Serial.println("Geen verbinding met site.");}
delay(100);
while (client.available())
{
char c = client.read();
if (c == '\n')
{
if (getAll.length()==0) { state=true; }
getAll = "";
}
else if (c != '\r') { getAll += String(c); }
if (state==true) { getBody += String(c); }
startTimer = millis();
}
if (getBody.length()>0) { break; }
}
Serial.println();
client.stop();
Serial.println(getBody);
}else{
getBody = "Verbinding met " + serverName + " is mislukt.";
Serial.println(getBody);
}
//return getBody;
}
//-------------------------------------------
void camerasetup()
{
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_SVGA;
config.jpeg_quality = 7; //0-63 lower number means higher quality
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_CIF;
config.jpeg_quality = 7; //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();
}
}
//-----------------------------
void wifisetup()
{
WiFi.mode(WIFI_STA);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(100);
conn++;
if (conn>500)
{
Serial.println(".");
}
}
Serial.println();
Serial.print("ESP32-CAM IP Address: ");
Serial.println(WiFi.localIP());
}
//----------------------------------
void ledsetup()
{
// configure LED PWM functionalitites
ledcSetup(ledChannel, freq, resolutie);

// attach the channel to the GPIO to be controlled
ledcAttachPin(lampen, ledChannel);
}



Bronnen:
P3DprinterCam
randomnerdtutorials.com/installing-the-esp32-board-in-arduino-ide-windows-instructions
randomnerdtutorials.com/esp32-cam-ai-thinker-pinout
randomnerdtutorials.com/esp32-cam-take-photo-save-microsd-card
randomnerdtutorials.com/esp32-cam-video-streaming-web-server-camera-home-assistant
randomnerdtutorials.com/esp32-pwm-arduino-id