Noise removal of audio

Hi @Pallavi_Lad ,

Yes, the connection shown in the diagram is correct.

No, it is not a header file. Kindly follow the steps below:

  1. Download AmebaILI9341.zip and extract AmebaILI9341.cpp
  2. Copy and replace the file contained in Arduino15 folder, C:\Users\\AppData\Local\Arduino15\packages\realtek\hardware\AmebaPro2\\libraries\SPI\src
  3. Make sure the ILI9341_SPI_FREQUENCY is set to 40000000 in your example.
  4. Compile and upload the code.

Please let us know if you are still unclear about the steps to replace the file.

Thank you.

Yeah sir , It is working
Thank You so much sir
And please solution for the noise removal
Thank you

Hi, would you like to try on digital or I2S mic for lower ambient noise? We have recently added I2S mic example to our Arduino SDK. Add SD Card Save Raw example (#387) · Ameba-AIoT/ameba-arduino-pro2@07bfaf3 · GitHub

Thank you.

Sorry no header file I2S.h is not there
Thank You

Hi @Pallavi_Lad ,

Kindly refer to the patch below for the I2S files and example.

i2s_patch.zip (2.6 KB)

Thank you.

Hi @KevinKL , Sir actually I am facing an trouble while doing the offline attendance monitor system
error:[VID Wrn]

 CH 0 MMF ENC Queue full 

error: vipnn not applied

which ever code I do upload I am facing error
/*******************************************************

* OFFLINE ATTENDANCE SYSTEM v16.15 - VIPNN FIXED

* AMB824 Pro2 + ILI9341 TFT (240x320)

*

* :white_check_mark: VIPNN FIXED — 3-channel init (CH0 H264 activates VOE)

* :white_check_mark: ALL FLICKER FIXED — single drawBitmap() per frame

* :white_check_mark: 30FPS SMOOTH VIDEO (33ms timing)

* :white_check_mark: LED BLINK: GREEN(Registered) + BLUE(Unknown) 500ms

* :white_check_mark: Everything else identical to v16.14

*******************************************************/

#include “VideoStream.h”

#include “SPI.h”

#include “AmebaILI9341.h”

#include “TJpg_Decoder.h”

#include “AmebaFatFS.h”

#include “NNFaceDetectionRecognition.h”

#include “StreamIO.h”

#include

// ─── Pin & Screen ─────────────────────────────────────

#define TFT_RESET 5

#define TFT_DC 4

#define TFT_CS SPI_SS

#define TFT_WIDTH 240

#define TFT_HEIGHT 320

// ─── Layout ───────────────────────────────────────────

#define HEADER_H 28

#define FOOTER_H 38

#define VIDEO_Y HEADER_H

#define VIDEO_H (TFT_HEIGHT - HEADER_H - FOOTER_H)

// ─── BOX ──────────────────────────────────────────────

#define BOX_W 220

#define BOX_H (VIDEO_H - 6)

#define BOX_X ((TFT_WIDTH - BOX_W) / 2)

#define BOX_Y (VIDEO_Y + 3)

#define BOX_T 10

// ─── Hardware ─────────────────────────────────────────

#define BUTTON_PIN 16

#define BLUE_LED LED_B

#define GREEN_LED LED_G

// ── CHANNELS — 3-channel fix for vipnn ──

#define CH_H264 0 // H264 — activates VOE engine (MUST be CH0)

#define CH_JPEG 1 // JPEG — TFT display

#define CH_NN 3 // NN face recognition

#define NN_W 576

#define NN_H 320

// ─── Files ────────────────────────────────────────────

#define USER_DIR “/users”

#define REG_FILE “/users/NEW_FILE.txt”

#define ATT_FILE “/attendance.csv”

// ─── Timing ───────────────────────────────────────────

#define VIDEO_FPS_MS 33

#define LED_MS 500

// ─── Colors ───────────────────────────────────────────

#define C_BLACK 0x0000

#define C_WHITE 0xFFFF

#define C_RED 0xF800

#define C_GREEN 0x07E0

#define C_BLUE 0x001F

#define C_YELLOW 0xFFE0

#define C_ORANGE 0xFD20

#define C_DGRAY 0x7BEF

#define C_NAVY 0x000F

// ─── Objects ──────────────────────────────────────────

VideoSetting cfgH264(VIDEO_FHD, 30, VIDEO_H264, 0); // CH0 — VOE activator

VideoSetting cfgJPEG(VIDEO_VGA, 30, VIDEO_JPEG, 1); // CH1 — display

VideoSetting cfgNN(NN_W, NN_H, 15, VIDEO_RGB, 0); // CH3 — NN

CameraSetting cfgCam;

AmebaILI9341 tft(TFT_CS, TFT_DC, TFT_RESET);

NNFaceDetectionRecognition facerecog;

StreamIO streamerNN(1, 1); // CH3 → facerecog

AmebaFatFS fs;

// ─── Framebuffer ──────────────────────────────────────

uint16_t *frameBuf = nullptr;

// ─── State ────────────────────────────────────────────

bool regMode = false;

bool lastBtn = HIGH;

unsigned long lastPress = 0;

int pressCount = 0;

String statusMsg = “”;

unsigned long statusTime = 0;

bool faceIn = false;

bool faceReg = false;

String faceName = “”;

String lastAttName = “”;

unsigned long lastFaceTime = 0;

uint32_t imgAddr = 0;

uint32_t imgLen = 0;

bool ledState = false;

unsigned long lastLed = 0;

bool isReg = false;

unsigned long frameCount = 0;

int currentFPS = 0;

uint16_t gBoxColor = C_WHITE;

// ─── Framebuf helpers ─────────────────────────────────

void fbFill(int x, int y, int w, int h, uint16_t c) {

int x0=x<0?0:x, x1=x+w>TFT_WIDTH ?TFT_WIDTH :x+w;

int y0=y<0?0:y, y1=y+h>TFT_HEIGHT?TFT_HEIGHT:y+h;

for (int r=y0; r<y1; r++)

for (int col=x0; col<x1; col++)

frameBuf[r*TFT_WIDTH+col]=c;

}

void fbHLine(int x, int y, int w, uint16_t c) {

if (y<0||y>=TFT_HEIGHT) return;

int x1=x+w>TFT_WIDTH?TFT_WIDTH:x+w;

for (int col=x<0?0:x; col<x1; col++)

frameBuf[y*TFT_WIDTH+col]=c;

}

void fbVLine(int x, int y, int h, uint16_t c) {

if (x<0||x>=TFT_WIDTH) return;

int y1=y+h>TFT_HEIGHT?TFT_HEIGHT:y+h;

for (int row=y<0?0:y; row<y1; row++)

frameBuf[row*TFT_WIDTH+x]=c;

}

// ─── 5x7 pixel font ───────────────────────────────────

static const uint8_t font5x7[][5] = {

{0x00,0x00,0x00,0x00,0x00},{0x00,0x00,0x5F,0x00,0x00},

{0x00,0x07,0x00,0x07,0x00},{0x14,0x7F,0x14,0x7F,0x14},

{0x24,0x2A,0x7F,0x2A,0x12},{0x23,0x13,0x08,0x64,0x62},

{0x36,0x49,0x55,0x22,0x50},{0x00,0x05,0x03,0x00,0x00},

{0x00,0x1C,0x22,0x41,0x00},{0x00,0x41,0x22,0x1C,0x00},

{0x08,0x2A,0x1C,0x2A,0x08},{0x08,0x08,0x3E,0x08,0x08},

{0x00,0x50,0x30,0x00,0x00},{0x08,0x08,0x08,0x08,0x08},

{0x00,0x60,0x60,0x00,0x00},{0x20,0x10,0x08,0x04,0x02},

{0x3E,0x51,0x49,0x45,0x3E},{0x00,0x42,0x7F,0x40,0x00},

{0x42,0x61,0x51,0x49,0x46},{0x21,0x41,0x45,0x4B,0x31},

{0x18,0x14,0x12,0x7F,0x10},{0x27,0x45,0x45,0x45,0x39},

{0x3C,0x4A,0x49,0x49,0x30},{0x01,0x71,0x09,0x05,0x03},

{0x36,0x49,0x49,0x49,0x36},{0x06,0x49,0x49,0x29,0x1E},

{0x00,0x36,0x36,0x00,0x00},{0x00,0x56,0x36,0x00,0x00},

{0x00,0x08,0x14,0x22,0x41},{0x14,0x14,0x14,0x14,0x14},

{0x41,0x22,0x14,0x08,0x00},{0x02,0x01,0x51,0x09,0x06},

{0x32,0x49,0x79,0x41,0x3E},{0x7E,0x11,0x11,0x11,0x7E},

{0x7F,0x49,0x49,0x49,0x36},{0x3E,0x41,0x41,0x41,0x22},

{0x7F,0x41,0x41,0x22,0x1C},{0x7F,0x49,0x49,0x49,0x41},

{0x7F,0x09,0x09,0x01,0x01},{0x3E,0x41,0x41,0x49,0x7A},

{0x7F,0x08,0x08,0x08,0x7F},{0x00,0x41,0x7F,0x41,0x00},

{0x20,0x40,0x41,0x3F,0x01},{0x7F,0x08,0x14,0x22,0x41},

{0x7F,0x40,0x40,0x40,0x40},{0x7F,0x02,0x04,0x02,0x7F},

{0x7F,0x04,0x08,0x10,0x7F},{0x3E,0x41,0x41,0x41,0x3E},

{0x7F,0x09,0x09,0x09,0x06},{0x3E,0x41,0x51,0x21,0x5E},

{0x7F,0x09,0x19,0x29,0x46},{0x46,0x49,0x49,0x49,0x31},

{0x01,0x01,0x7F,0x01,0x01},{0x3F,0x40,0x40,0x40,0x3F},

{0x1F,0x20,0x40,0x20,0x1F},{0x7F,0x20,0x18,0x20,0x7F},

{0x63,0x14,0x08,0x14,0x63},{0x03,0x04,0x78,0x04,0x03},

{0x61,0x51,0x49,0x45,0x43},{0x00,0x00,0x7F,0x41,0x41},

{0x02,0x04,0x08,0x10,0x20},{0x41,0x41,0x7F,0x00,0x00},

{0x04,0x02,0x01,0x02,0x04},{0x40,0x40,0x40,0x40,0x40},

{0x00,0x01,0x02,0x04,0x00},{0x20,0x54,0x54,0x54,0x78},

{0x7F,0x48,0x44,0x44,0x38},{0x38,0x44,0x44,0x44,0x20},

{0x38,0x44,0x44,0x48,0x7F},{0x38,0x54,0x54,0x54,0x18},

{0x08,0x7E,0x09,0x01,0x02},{0x08,0x14,0x54,0x54,0x3C},

{0x7F,0x08,0x04,0x04,0x78},{0x00,0x44,0x7D,0x40,0x00},

{0x20,0x40,0x44,0x3D,0x00},{0x00,0x7F,0x10,0x28,0x44},

{0x00,0x41,0x7F,0x40,0x00},{0x7C,0x04,0x18,0x04,0x78},

{0x7C,0x08,0x04,0x04,0x78},{0x38,0x44,0x44,0x44,0x38},

{0x7C,0x14,0x14,0x14,0x08},{0x08,0x14,0x14,0x18,0x7C},

{0x7C,0x08,0x04,0x04,0x08},{0x48,0x54,0x54,0x54,0x20},

{0x04,0x3F,0x44,0x40,0x20},{0x3C,0x40,0x40,0x40,0x7C},

{0x1C,0x20,0x40,0x20,0x1C},{0x3C,0x40,0x30,0x40,0x3C},

{0x44,0x28,0x10,0x28,0x44},{0x0C,0x50,0x50,0x50,0x3C},

{0x44,0x64,0x54,0x4C,0x44},{0x00,0x08,0x36,0x41,0x00},

{0x00,0x00,0x7F,0x00,0x00},{0x00,0x41,0x36,0x08,0x00},

{0x08,0x08,0x2A,0x1C,0x08},

};

void fbChar(int x, int y, char ch, uint16_t c, int s=1) {

if (ch<32||ch>126) ch=32;

const uint8_t *bm=font5x7[ch-32];

for (int col=0;col<5;col++) {

uint8_t bits=bm[col];

for (int row=0;row<7;row++) {

if (bits&(1<<row)) {

for (int sy=0;sy<s;sy++)

for (int sx=0;sx<s;sx++) {

int px=x+col*s+sx,py=y+row*s+sy;

if (px>=0&&px<TFT_WIDTH&&py>=0&&py<TFT_HEIGHT)

frameBuf[py*TFT_WIDTH+px]=c;

}

}

}

}

}

void fbText(int x, int y, const char *str, uint16_t c, int s=1) {

int cx=x;

while(*str){fbChar(cx,y,*str++,c,s);cx+=(5+1)*s;}

}

int fbTextW(const char *str, int s=1){

return strlen(str)*(5+1)*s;

}

// ─── TJpgDec callback — into frameBuf only ────────────

bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bmp) {

if (!frameBuf) return false;

for (int row=0; row<h; row++) {

int dy=y+row;

if (dy<VIDEO_Y||dy>=VIDEO_Y+VIDEO_H) continue;

for (int col=0; col<w; col++) {

int dx=x+col;

if (dx<0||dx>=TFT_WIDTH) continue;

frameBuf[dy*TFT_WIDTH+dx]=bmp[row*w+col];

}

}

return true;

}

// ─── Box border into frameBuf ─────────────────────────

void fbDrawBox(uint16_t c) {

fbFill(BOX_X, BOX_Y, BOX_W, BOX_T, c);

fbFill(BOX_X, BOX_Y+BOX_H-BOX_T, BOX_W, BOX_T, c);

fbFill(BOX_X, BOX_Y+BOX_T, BOX_T, BOX_H-2*BOX_T, c);

fbFill(BOX_X+BOX_W-BOX_T,BOX_Y+BOX_T, BOX_T, BOX_H-2*BOX_T, c);

}

// ─── LED blink — identical to v16.14 ──────────────────

void updateLEDs() {

if (millis()-lastLed<LED_MS) return;

lastLed=millis(); ledState=!ledState;

if (faceReg) {

digitalWrite(GREEN_LED,ledState); digitalWrite(BLUE_LED,LOW);

} else if (faceIn) {

digitalWrite(BLUE_LED,ledState); digitalWrite(GREEN_LED,LOW);

} else {

digitalWrite(BLUE_LED,LOW); digitalWrite(GREEN_LED,LOW);

}

}

String getTime() {

unsigned long s=millis()/1000; char b[9];

snprintf(b,9,“%02lu:%02lu:%02lu”,s/3600%24,s/60%60,s%60);

return String(b);

}

String getDate() {

char b[12];

snprintf(b,12,“2026-02-%02d”,(int)(14+(millis()/86400000UL)%28));

return String(b);

}

void statusShow(String m){statusMsg=m;statusTime=millis();}

// ─── SD — identical to v16.14 ─────────────────────────

void initSD() {

fs.begin();

if (!fs.exists(USER_DIR)) fs.mkdir(USER_DIR);

if (!fs.exists(REG_FILE)) {

File f=fs.open(REG_FILE);

if(f){f.println(“# REGISTERED”);f.close();}

}

if (!fs.exists(ATT_FILE)) {

File f=fs.open(ATT_FILE);

if(f){f.println(“Name,Date,Time”);f.close();}

}

fs.end();

}

bool nameRegistered(String name) {

if(name==“unknown”||name.length()==0) return false;

fs.begin(); File f=fs.open(REG_FILE); bool found=false;

if(f){while(f.available()){String l=f.readStringUntil(‘\n’);l.trim();if(l==name){found=true;break;}}f.close();}

fs.end(); return found;

}

void saveName(String name) {

if(nameRegistered(name)) return;

fs.begin(); File f=fs.open(REG_FILE);

if(f){f.seek(f.size());f.println(name);f.close();}

fs.end();

}

void markAttendance(String name) {

String date=getDate(),time=getTime();

fs.begin(); File rf=fs.open(ATT_FILE); bool already=false;

if(rf){while(rf.available()){String l=rf.readStringUntil(‘\n’);if(l.indexOf(name+“,”+date)>=0){already=true;break;}}rf.close();}

if(!already){File wf=fs.open(ATT_FILE);if(wf){wf.seek(wf.size());wf.println(name+“,”+date+“,”+time);wf.close();}statusShow("Att: "+name);}

fs.end();

}

// ─── Face callback — identical to v16.14 ──────────────

void FRCallback(std::vector results) {

if(isReg) return;

if(results.empty()||facerecog.getResultCount()==0){

faceIn=false;faceReg=false;faceName=“”;gBoxColor=C_WHITE;return;

}

String name=String(results[0].name());

if(name.length()==0||name==" "){

faceIn=false;faceReg=false;faceName=“”;gBoxColor=C_WHITE;return;

}

faceIn=true;faceName=name;lastFaceTime=millis();

if(name==“unknown”){

faceReg=false;gBoxColor=C_RED;

} else {

faceReg=nameRegistered(name);

gBoxColor=faceReg?C_GREEN:C_RED;

if(faceReg&&name!=lastAttName){markAttendance(name);lastAttName=name;}

}

}

// ─── Button — identical to v16.14 ─────────────────────

void handleButton() {

bool btn=digitalRead(BUTTON_PIN);

if(btn==LOW&&lastBtn==HIGH){

delay(50); unsigned long now=millis();

if(now-lastPress<500){if(++pressCount>=2){regMode=false;statusShow(“REG OFF”);pressCount=0;}}

else{pressCount=1;}

lastPress=now;

if(pressCount==1&&!regMode){regMode=true;statusShow(“REG ON”);}

}

lastBtn=btn;

}

void updateFPS() {

static unsigned long lastFPSTime=0;

if(millis()-lastFPSTime>=1000){currentFPS=frameCount;frameCount=0;lastFPSTime=millis();}

}

// ─── Serial — identical to v16.14 ─────────────────────

void handleSerial() {

if(!Serial.available()) return;

String cmd=Serial.readStringUntil(‘\n’); cmd.trim();

if(cmd.startsWith(“REG=”)&&regMode){

String name=cmd.substring(4); name.trim();

if(name.length()==0) return;

isReg=true;

tft.fillRectangle(0,0,TFT_WIDTH,TFT_HEIGHT,C_BLUE);

tft.setForeground(C_WHITE);tft.setFontSize(2);

tft.setCursor(20,120);tft.print(“REGISTERING”);

tft.setFontSize(1);tft.setCursor(70,150);tft.print(name);

facerecog.registerFace(name.c_str());delay(800);

saveName(name);

facerecog.backupRegisteredFace();delay(500);

tft.fillRectangle(0,90,TFT_WIDTH,130,C_GREEN);

tft.setForeground(C_BLACK);tft.setFontSize(3);

tft.setCursor(30,130);tft.print(“SUCCESS!”);

delay(1200);

statusShow("Saved: "+name);

regMode=false;isReg=false;

memset(frameBuf,0,TFT_WIDTH*TFT_HEIGHT*sizeof(uint16_t));

Serial.println("Registered: "+name);

}

}

// ─── Render — identical to v16.14 ─────────────────────

void renderFrame() {

if(isReg) return;

frameCount++;

Camera.getImage(CH_JPEG,&imgAddr,&imgLen);

if(imgAddr&&imgLen>0)

TJpgDec.drawJpg(0,VIDEO_Y,(uint8_t*)imgAddr,imgLen);

fbDrawBox(gBoxColor);

fbFill(0,0,TFT_WIDTH,HEADER_H,C_NAVY);

fbHLine(0,HEADER_H-1,TFT_WIDTH,C_BLUE);

if(regMode){

fbText(4,6,“** REG MODE **”,C_YELLOW,1);

fbText(4,18,“Serial: REG=Name”,C_ORANGE,1);

} else {

fbText(4,6,“v16.15 ATTENDANCE”,C_WHITE,1);

char fps[12]; snprintf(fps,12,“FPS:%d”,currentFPS);

fbText(4,18,fps,C_DGRAY,1);

}

String t=getTime(); int tw=fbTextW(t.c_str(),1);

fbText(TFT_WIDTH-tw-4,11,t.c_str(),C_YELLOW,1);

uint16_t footerBg=regMode?C_ORANGE:C_NAVY;

fbFill(0,TFT_HEIGHT-FOOTER_H,TFT_WIDTH,FOOTER_H,footerBg);

fbHLine(0,TFT_HEIGHT-FOOTER_H,TFT_WIDTH,C_BLUE);

String footerTxt; uint16_t footerCol;

if(regMode){footerTxt=“REG MODE”;footerCol=C_BLACK;}

else if(!faceIn){footerTxt=“NO FACE”;footerCol=C_DGRAY;}

else if(faceReg){footerTxt=faceName;footerCol=C_GREEN;}

else{footerTxt=“UNKNOWN”;footerCol=C_RED;}

if(footerTxt.length()>20) footerTxt=footerTxt.substring(0,17)+“…”;

int fw=fbTextW(footerTxt.c_str(),2);

int fx=(TFT_WIDTH-fw)/2; if(fx<4)fx=4;

int fy=TFT_HEIGHT-FOOTER_H+(FOOTER_H-14)/2;

fbText(fx,fy,footerTxt.c_str(),footerCol,2);

const char *lbl=!faceIn?“NO FACE”:faceReg?“REGISTERED”:“UNKNOWN”;

int lw=fbTextW(lbl,1),lx=BOX_X+(BOX_W-lw)/2,ly=BOX_Y+(BOX_H-7)/2;

fbFill(lx-6,ly-4,lw+12,15,C_BLACK);

fbText(lx,ly,lbl,gBoxColor,1);

if(statusMsg!=“”&&millis()-statusTime<=3000){

int sw=fbTextW(statusMsg.c_str(),1)+20;

int sx=std::max(5,(TFT_WIDTH-sw)/2),sy=TFT_HEIGHT/2-10;

fbFill(sx,sy,sw,20,C_BLACK);

fbHLine(sx,sy,sw,C_YELLOW);fbHLine(sx,sy+19,sw,C_YELLOW);

fbVLine(sx,sy,20,C_YELLOW);fbVLine(sx+sw-1,sy,20,C_YELLOW);

fbText(sx+8,sy+6,statusMsg.c_str(),C_YELLOW,1);

}

tft.drawBitmap(0,0,TFT_WIDTH,TFT_HEIGHT,frameBuf);

}

// ─────────────────────────────────────────────────────

void setup() {

Serial.begin(115200);

delay(1500);

Serial.println(“v16.15 - VIPNN FIXED + NO FLICKER”);

pinMode(BLUE_LED,OUTPUT); pinMode(GREEN_LED,OUTPUT);

pinMode(BUTTON_PIN,INPUT_PULLUP);

frameBuf=(uint16_t*)malloc(TFT_WIDTH*TFT_HEIGHT*sizeof(uint16_t));

if(!frameBuf){Serial.println(“FATAL: malloc!”);while(1)delay(1000);}

memset(frameBuf,0,TFT_WIDTH*TFT_HEIGHT*sizeof(uint16_t));

SPI.setDefaultFrequency(40000000);

tft.begin(); tft.setRotation(0); tft.clr();

TJpgDec.setJpgScale(2);

TJpgDec.setCallback(tft_output);

initSD();

/* ══════════════════════════════════════════

3-CHANNEL INIT — fixes vipnn not applied

CH0 H264 must be configured first to

activate the VOE/VIPNN hardware engine

══════════════════════════════════════════ */

Camera.configVideoChannel(CH_H264, cfgH264); // CH0 first — activates VOE

Camera.configVideoChannel(CH_JPEG, cfgJPEG); // CH1 — display

Camera.configVideoChannel(CH_NN, cfgNN); // CH3 — NN

Camera.videoInit();

// Start CH0 H264 — must begin to keep VOE active

// No StreamIO needed — just channelBegin keeps VOE alive

Camera.channelBegin(CH_H264);

facerecog.configVideo(cfgNN);

facerecog.modelSelect(FACE_RECOGNITION,NA_MODEL,

DEFAULT_SCRFD,DEFAULT_MOBILEFACENET);

facerecog.begin();

facerecog.setResultCallback(FRCallback);

streamerNN.registerInput(Camera.getStream(CH_NN));

streamerNN.registerOutput(facerecog);

streamerNN.begin();

Camera.channelBegin(CH_JPEG);

Camera.channelBegin(CH_NN);

facerecog.restoreRegisteredFace();

tft.fillRectangle(0,0,TFT_WIDTH,TFT_HEIGHT,C_GREEN);

tft.setForeground(C_BLACK);tft.setFontSize(3);

tft.setCursor(40,140);tft.print(“READY!”);

delay(1200);

memset(frameBuf,0,TFT_WIDTH*TFT_HEIGHT*sizeof(uint16_t));

Serial.println(“v16.15 running!”);

}

void loop() {

if(!isReg&&faceIn&&millis()-lastFaceTime>1500){

faceIn=false;faceReg=false;faceName=“”;gBoxColor=C_WHITE;

}

updateLEDs();

updateFPS();

handleButton();

handleSerial();

static unsigned long lastFrame=0;

if(millis()-lastFrame>=VIDEO_FPS_MS){

lastFrame=millis();

renderFrame();

}

}

here is the code where i am facing error

#include “VideoStream.h”

#include “SPI.h”

#include “AmebaILI9341.h”

#include <JPEGDEC_Libraries/JPEGDEC.h>

#include “NNFaceDetectionRecognition.h”

#include “StreamIO.h”

#include “AmebaFatFS.h”

/* ===== CHANNELS ===== */

#define CHANNEL_JPEG 0

#define CHANNEL_NN 3

/* ===== TFT PINS ===== */

#define TFT_RESET 5

#define TFT_DC 4

#define TFT_CS SPI_SS

/* ===== GPIO ===== */

#define REG_BUTTON 16

#define BLUE_LED LED_B

#define GREEN_LED LED_G

/* ===== DISPLAY — PORTRAIT 240x320 ===== */

#define ILI9341_SPI_FREQUENCY 40000000

#define TFT_W 240

#define TFT_H 320

/* ===== JPEG SOURCE SIZE (after SCALE_HALF of VGA 640x480) ===== */

#define CAM_W 320 // landscape width after half scale

#define CAM_H 240 // landscape height after half scale

/* ===== LAYOUT (portrait) ===== */

#define HEADER_H 20

#define STATUS_H 20

#define VIDEO_Y HEADER_H // 20

#define VIDEO_H (TFT_H - HEADER_H - STATUS_H) // 280

#define STATUS_Y (TFT_H - STATUS_H) // 300

/* ===== NO-FACE TIMEOUT ===== */

#define NO_FACE_MS 300

/* ===== COLORS RGB565 ===== */

#define C_BLACK 0x0000

#define C_WHITE 0xFFFF

#define C_RED 0xF800

#define C_GREEN 0x07E0

#define C_BLUE 0x001F

#define C_CYAN 0x07FF

#define C_YELLOW 0xFFE0

#define C_ORANGE 0xFD20

#define C_DGRAY 0x7BEF

#define C_NAVY 0x000F

/* ===== SD ===== */

#define ATT_FILE “/attendance.csv”

/* ===== VIDEO CONFIGS ===== */

VideoSetting configJPEG(VIDEO_VGA, 30, VIDEO_JPEG, 1);

VideoSetting configNN(576, 320, 10, VIDEO_RGB, 0);

/* ===== OBJECTS ===== */

AmebaILI9341 tft(TFT_CS, TFT_DC, TFT_RESET);

JPEGDEC jpeg;

NNFaceDetectionRecognition facerecog;

StreamIO streamNN(1, 1);

AmebaFatFS fs;

/* ===== FRAME BUFFER — heap allocated ===== */

uint32_t img_addr = 0;

uint32_t img_len = 0;

uint16_t *frameBuf = nullptr; // TFT_W * TFT_H * 2 = 153600 bytes

/* ===== STATE ===== */

bool regMode = false;

bool lastBtn = HIGH;

/* ===== FACE STATE ===== */

bool faceDetected = false;

unsigned long lastFaceTime = 0;

std::vector lastResults;

/* ===== ATTENDANCE — in-memory duplicate tracking ===== */

#define MAX_MARKED 50

char markedNames[MAX_MARKED][32];

int markedCount = 0;

bool alreadyMarked(const char *name) {

for (int i = 0; i < markedCount; i++)

if (strcmp(markedNames[i], name) == 0) return true;

return false;

}

void addToMarked(const char *name) {

if (markedCount < MAX_MARKED)

strncpy(markedNames[markedCount++], name, 31);

}

/* ===========================

JPEG DRAW — rotate 90° CW inline

Source: landscape CAM_W(320) x CAM_H(240)

Dest: portrait TFT_W(240) x TFT_H(320)

90° CW formula:

dst_col = CAM_H - 1 - src_row → 0..239 = TFT_W

dst_row = src_col → 0..319 = TFT_H

VIDEO area occupies dst_rows VIDEO_Y..STATUS_Y-1 (20..299)

Camera rows 0..CAM_H map to VIDEO_H(280) rows after scaling:

dst_row = VIDEO_Y + src_col * VIDEO_H / CAM_W

=========================== */

int JPEGDraw(JPEGDRAW *pDraw) {

if (!frameBuf) return 0;

for (int y = 0; y < pDraw->iHeight; y++) {

int src_row = pDraw->y + y;

if (src_row < 0 || src_row >= CAM_H) continue;

for (int x = 0; x < pDraw->iWidth; x++) {

int src_col = pDraw->x + x;

if (src_col < 0 || src_col >= CAM_W) continue;

// 90° CW rotation

int dst_col = CAM_H - 1 - src_row; // 0..239

int dst_row = VIDEO_Y + src_col * VIDEO_H / CAM_W; // 20..299

if (dst_col < 0 || dst_col >= TFT_W) continue;

if (dst_row < VIDEO_Y || dst_row >= STATUS_Y) continue;

frameBuf[dst_row * TFT_W + dst_col] =

pDraw->pPixels[y * pDraw->iWidth + x];

}

}

return 1;

}

/* ===========================

FRAMEBUF DRAW HELPERS

=========================== */

void fbFill(int x, int y, int w, int h, uint16_t c) {

int x0 = x < 0 ? 0 : x, x1 = x+w > TFT_W ? TFT_W : x+w;

int y0 = y < 0 ? 0 : y, y1 = y+h > TFT_H ? TFT_H : y+h;

for (int r = y0; r < y1; r++)

for (int col = x0; col < x1; col++)

frameBuf[r * TFT_W + col] = c;

}

void fbHLine(int x, int y, int w, uint16_t c) {

if (y < 0 || y >= TFT_H) return;

int x1 = x+w > TFT_W ? TFT_W : x+w;

for (int col = x < 0 ? 0 : x; col < x1; col++)

frameBuf[y * TFT_W + col] = c;

}

void fbVLine(int x, int y, int h, uint16_t c) {

if (x < 0 || x >= TFT_W) return;

int y1 = y+h > TFT_H ? TFT_H : y+h;

for (int row = y < 0 ? 0 : y; row < y1; row++)

frameBuf[row * TFT_W + x] = c;

}

void fbRect(int x, int y, int w, int h, uint16_t c) {

fbHLine(x, y, w, c);

fbHLine(x, y+h-1, w, c);

fbVLine(x, y, h, c);

fbVLine(x+w-1, y, h, c);

}

void fbThickRect(int x, int y, int w, int h, uint16_t c, int t) {

for (int i = 0; i < t; i++)

fbRect(x+i, y+i, w-2*i, h-2*i, c);

}

/* ===========================

TIME STRING (uptime hh:mm:ss)

=========================== */

String getTimeStr() {

unsigned long s = millis() / 1000;

char buf[9];

sprintf(buf, “%02lu:%02lu:%02lu”, s/3600, (s%3600)/60, s%60);

return String(buf);

}

/* ===========================

MARK ATTENDANCE TO SD

=========================== */

bool markAttendance(String name) {

if (alreadyMarked(name.c_str())) return false; // skip — already saved

String ts = getTimeStr();

File log = fs.open(ATT_FILE, FA_WRITE | FA_OPEN_APPEND);

if (log) {

log.println(name + “,” + ts);

log.close();

addToMarked(name.c_str());

Serial.println("ATT SAVED: " + name + " @ " + ts);

return true;

}

Serial.println("ATT ERROR: SD write failed for " + name);

return false;

}

/* ===========================

FACE CALLBACK

=========================== */

void FRPostProcess(std::vector results) {

lastResults = results;

faceDetected = (results.size() > 0);

if (faceDetected) {

lastFaceTime = millis();

Serial.println("FACE: " + String(results[0].name()));

}

}

/* ===========================

SETUP

=========================== */

void setup() {

Serial.begin(115200);

pinMode(REG_BUTTON, INPUT_PULLUP);

pinMode(BLUE_LED, OUTPUT);

pinMode(GREEN_LED, OUTPUT);

digitalWrite(BLUE_LED, LOW);

digitalWrite(GREEN_LED, LOW);

/* ── HEAP BUFFER ── */

frameBuf = (uint16_t*)malloc(TFT_W * TFT_H * sizeof(uint16_t));

if (!frameBuf) {

Serial.println(“FATAL: frameBuf malloc failed!”);

while (1) delay(1000);

}

memset(frameBuf, 0, TFT_W * TFT_H * sizeof(uint16_t));

/* ── TFT ── */

SPI.setDefaultFrequency(ILI9341_SPI_FREQUENCY);

tft.begin();

tft.setRotation(4); // portrait 240x320

// if upside-down change to: tft.setRotation(2)

/* ── WELCOME SCREEN ── */

tft.fillRectangle(0, 0, TFT_W, TFT_H, C_NAVY);

// header stripe

tft.fillRectangle(0, 0, TFT_W, 40, C_BLUE);

tft.setForeground(C_WHITE);

tft.setFontSize(2);

tft.setCursor(14, 12);

tft.print(“ATTENDANCE”);

tft.fillRectangle(0, 40, TFT_W, 2, C_CYAN);

// info

tft.setForeground(C_CYAN);

tft.setFontSize(1);

tft.setCursor(68, 75);

tft.print(“AMB82-MINI”);

tft.setForeground(C_WHITE);

tft.setCursor(20, 100);

tft.print(“Face Recognition System”);

tft.setCursor(44, 125);

tft.print(“Portrait 240 x 320”);

// divider

tft.fillRectangle(20, 155, TFT_W-40, 1, C_DGRAY);

// hints

tft.setForeground(C_DGRAY);

tft.setCursor(8, 170);

tft.print(“BTN = Toggle REG mode”);

tft.setCursor(8, 188);

tft.print(“REG=Name to register”);

tft.setCursor(8, 206);

tft.print(“DEL=Name to delete”);

tft.setCursor(8, 224);

tft.print(“RESET to clear all”);

// bottom bar

tft.fillRectangle(0, TFT_H-32, TFT_W, 32, C_BLUE);

tft.setForeground(C_YELLOW);

tft.setCursor(52, TFT_H-18);

tft.print(“Initializing…”);

delay(2000);

/* ── SD ── */

fs.begin();

if (!fs.exists(ATT_FILE)) {

File h = fs.open(ATT_FILE, FA_WRITE);

if (h) {

h.println(“Name,Time”);

h.close();

Serial.println(“SD: attendance.csv created”);

} else {

Serial.println(“SD: WARNING — could not create attendance.csv”);

}

} else {

Serial.println(“SD: attendance.csv found”);

}

/* ── CAMERA + NN ── */

Camera.configVideoChannel(CHANNEL_JPEG, configJPEG);

Camera.configVideoChannel(CHANNEL_NN, configNN);

Camera.videoInit();

facerecog.configVideo(configNN);

facerecog.modelSelect(FACE_RECOGNITION, NA_MODEL, DEFAULT_SCRFD, DEFAULT_MOBILEFACENET);

facerecog.begin();

facerecog.restoreRegisteredFace();

facerecog.setResultCallback(FRPostProcess);

streamNN.registerInput(Camera.getStream(CHANNEL_NN));

streamNN.setStackSize();

streamNN.setTaskPriority();

streamNN.registerOutput(facerecog);

streamNN.begin();

Camera.channelBegin(CHANNEL_JPEG);

Camera.channelBegin(CHANNEL_NN);

Serial.println(“READY — BTN=REG | REG=Name | DEL=Name | RESET”);

}

/* ===========================

LOOP

=========================== */

void loop() {

/* ── BUTTON ── */

bool btn = digitalRead(REG_BUTTON);

if (btn == LOW && lastBtn == HIGH) {

regMode = !regMode;

Serial.println(regMode ? “REG MODE ON” : “NORMAL MODE”);

delay(200);

}

lastBtn = btn;

/* ── SERIAL ── */

if (Serial.available()) {

String cmd = Serial.readStringUntil(‘\n’); cmd.trim();

if (cmd.startsWith(“REG=”) && regMode) {

String n = cmd.substring(4); n.trim();

if (n.length()) {

facerecog.registerFace(n.c_str());

facerecog.backupRegisteredFace();

Serial.println("Registered: " + n);

}

} else if (cmd.startsWith(“DEL=”)) {

String n = cmd.substring(4); n.trim();

facerecog.removeFace(n);

facerecog.backupRegisteredFace();

Serial.println("Deleted: " + n);

} else if (cmd == “RESET”) {

facerecog.resetRegisteredFace();

facerecog.backupRegisteredFace();

markedCount = 0; // clear in-memory attendance too

Serial.println(“All faces + attendance memory cleared”);

}

}

/* ── FACE TIMEOUT ── */

bool faceNow = faceDetected &&

((millis() - lastFaceTime) < NO_FACE_MS);

/* ── DECODE JPEG → frameBuf (rotated 90°CW by JPEGDraw) ── */

Camera.getImage(CHANNEL_JPEG, &img_addr, &img_len);

if (img_len > 0) {

// clear video area before decode

fbFill(0, VIDEO_Y, TFT_W, VIDEO_H, C_BLACK);

jpeg.openFLASH((uint8_t*)img_addr, img_len, JPEGDraw);

jpeg.decode(0, 0, JPEG_SCALE_HALF); // 640x480 → 320x240 → rotated into portrait

jpeg.close();

}

fbFill(0, 0, TFT_W, HEADER_H, C_NAVY);

fbFill(0, STATUS_Y, TFT_W, STATUS_H, regMode ? C_ORANGE : C_NAVY);

/* ── FACE BOX INTO FRAMEBUF ── */

bool isReg = false;

char nm[64] = “”;

int nameX = 5, nameY = VIDEO_Y + 4;

uint16_t nameCol = C_WHITE;

if (!faceNow) {

// Guide box centered in video area

int bx = (TFT_W - 120) / 2; // 60

int by = VIDEO_Y + (VIDEO_H - 150) / 2; // 85

fbThickRect(bx, by, 120, 150, C_WHITE, 2);

digitalWrite(BLUE_LED, LOW);

digitalWrite(GREEN_LED, LOW);

} else {

FaceRecognitionResult r = lastResults[0];

String name = String(r.name());

isReg = (name != “unknown”);

strncpy(nm, name.c_str(), 63);

digitalWrite(BLUE_LED, !isReg ? HIGH : LOW);

digitalWrite(GREEN_LED, isReg ? HIGH : LOW);

// NN coords are landscape 0.0-1.0

// After 90°CW rotation applied in JPEGDraw:

// portrait_x = (1 - y_norm) * TFT_W

// portrait_y = VIDEO_Y + x_norm * VIDEO_H

int x1 = (int)((1.0f - r.yMax()) * TFT_W);

int y1 = VIDEO_Y + (int)(r.xMin() * VIDEO_H);

int w1 = (int)((r.yMax() - r.yMin()) * TFT_W);

int h1 = (int)((r.xMax() - r.xMin()) * VIDEO_H);

x1 = x1 < 0 ? 0 : (x1 > TFT_W-4 ? TFT_W-4 : x1);

y1 = y1 < VIDEO_Y ? VIDEO_Y : y1;

w1 = w1 < 8 ? 8 : w1;

h1 = h1 < 8 ? 8 : h1;

nameCol = isReg ? C_GREEN : C_RED;

fbThickRect(x1, y1, w1, h1, nameCol, 3);

nameX = x1;

nameY = (y1 > VIDEO_Y + 18) ? y1 - 18 : y1 + h1 + 2;

nameY = nameY < VIDEO_Y ? VIDEO_Y : nameY;

nameY = nameY > STATUS_Y-16 ? STATUS_Y-16 : nameY;

if (isReg) markAttendance(name);

}

/* ── PUSH FULL FRAME TO TFT (single call = no flicker) ── */

tft.drawBitmap(0, 0, TFT_W, TFT_H, frameBuf);

/* ── TEXT OVERLAYS (drawn after bitmap) ── */

// Header

tft.setFontSize(1);

tft.setForeground(C_CYAN);

tft.setCursor(4, 6);

tft.print(regMode ? “** REG MODE **” : “ATTENDANCE”);

tft.setForeground(C_WHITE);

tft.setCursor(TFT_W - 54, 6); // right-aligned time

tft.print(getTimeStr());

// No face label

if (!faceNow) {

tft.setForeground(C_WHITE);

tft.setFontSize(1);

int bx = (TFT_W - 120) / 2;

int by = VIDEO_Y + (VIDEO_H - 150) / 2;

tft.setCursor(bx + 22, by + 68);

tft.print(“NO FACE”);

}

// Face name

if (faceNow && strlen(nm) > 0) {

tft.setForeground(nameCol);

tft.setFontSize(2);

tft.setCursor(nameX, nameY);

tft.print(isReg ? nm : “Unknown”);

}

// Status bar text

tft.setFontSize(1);

tft.setCursor(4, STATUS_Y + 6);

if (regMode) {

tft.setForeground(C_YELLOW);

tft.print(“Serial: REG=YourName”);

} else if (!faceNow) {

tft.setForeground(C_DGRAY);

tft.print(“Waiting for face…”);

} else if (isReg) {

tft.setForeground(C_GREEN);

tft.print("Marked: ");

tft.print(nm);

} else {

tft.setForeground(C_RED);

tft.print(“Unknown — not registered”);

}

}
This is an another code where I am facing issue with display rotation if I change to the landscape it will display portrait and vice versa

Please give me solution
Thank you

Hi @Pallavi_Lad ,

For the first issue “error: vipnn not applied”, you might need to call Camera.channelBegin(CH_JPEG);before configuring video for NN, please refer to the fixed copy of code.

Thank you.

fixed_1st_part.zip (5.5 KB)

Hi there,
On the display camera is not displaying only
But error has gonna
Thank you

Hi @Pallavi_Lad,

If conventional noise reduction methods aren’t able to fully eliminate background noise, you can consider exploring the open-source tool VoiceFixer (GitHub - haoheliu/voicefixer: General Speech Restoration · GitHub) to post-process your recorded audio.