Continução de DIY Sensor de Pulso IR.
A idéia agora é verificar se com um foto-detector IR obtemos um circuito eletrônico mais sensível às pulsações.
| Pinagem Led comum | Pinagem Foto-Detector |
|---|---|
![]() | ![]() |
Note que estes componentes são fisicamente similares mas não iguais.
Fisicamente a montagem ficou como mostrado nas próximas figuras:

Implementando uma IR para rodar à 50 Hz, ou 0,02 segundos. Usado Timer 2, evitando conflitos como possível uso de funções delay, milis, etc. Timer 2 é de 8-bits. Realizando cálculos:
> fs = 50;>> T=1/fsT = 0.02>> CS2=[1 8 32 64 128 256 1024];>> CMR2=(16E6./(CS2*fs))-1CMR2 = 3.2e+05 39999 9999 4999 2499 1249 311.5>> % menor valor = 311 que "não cabe" em 8-bitsPode-se usar o Timer 1, que é de 16-bits. Recalculando:
xxxxxxxxxx>> % Mudando para timer 1>> CS1=[1 8 64 256 1024];>> CMR1=(16E6./(CS1*fs))-1CMR1 = 3.2e+05 39999 4999 1249 311.5Adotando prescaler para timer no valor de 256 (CS12=1; CS11=0; CS10=0) e fazendo CMR1=1249.
Código para Arduíno (pulse_monitor_2.ino):
x/* Monitor de pulsação Teste usando foto-detector Fernando Passold, em 10/10/2024*/const byte analogPin = A0; // pino (A/D) que recebe sinal analógicoint x; // dados lidos no A/D 0 do Arduínovoid setup() { // put your setup code here, to run once: // Programando a ISR à 50 Hz usando timer 1 cli();//stop interrupts //set timer1 interrupt at 50 Hz TCCR1A = 0; // set entire TCCR1A register to 0 TCCR1B = 0; // same for TCCR1B TCNT1 = 0; //initialize counter value to 0 // set compare match register for 1hz increments OCR1A = 1249; // = (16*10^6) / (50*256) - 1 (must be <65536) // turn on CTC mode TCCR1B |= (1 << WGM12); // Set CS12 bits for 256 prescaler TCCR1B |= (1 << CS12); // enable timer compare interrupt TIMSK1 |= (1 << OCIE1A); Serial.begin(115200); // setup serial while (!Serial) { ; // Aguarda até que a porta serial esteja pronta - normalmente 10 ms } Serial.println(" "); Serial.println("Monitorando foto-detector: "); sei();//allow interrupts}ISR(TIMER1_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED) // Atualiza varíavel x contendo valor lido em A0 x = analogRead(analogPin); // *(5.0/1024.0); // converte para faixa 0 á 5 Volts // não é recomendável enviar dados pela serial dentro de um ISR, mas testando... Serial.println(x); }void loop() { // put your main code here, to run repeatedly: // nada a ser feito aqui}Este código permitiu capturar a seguinte sequência de dados:

Os últimos segundos de captura mostrados (nível do sinal aumenta), correspondo ao que ocorre quando usuário remove o dedo do conjunto sensor.
Não corresponde ao tipo de sinal desejado ⚠️
Uma nova configuração física para o conjunto sensor foi testada:

E desta forma foram obtidos os seguintes dados:
Sem o dedo posicionado entre os sensores leitura na faixa: [417 432].
Com o dedo "bloqueando" o fluxo de luz, a leitura varia na faixa: [1015. 1023]:

Vamos tentar trabalhar com este "setup"...
Código (pulse_monitor_fpb.ino):
xxxxxxxxxx/* Monitor de pulsação Teste usando foto-detector Rotina com Filtro Passa Faixa Fernando Passold, em 10/10/2024*/const byte analogPin = A0; // pino (A/D) que recebe sinal analógicoconst byte monitor_isr = 7; // pino 7: para monitor freq e dutty-cycle da ISR (osciloscópio)bool state = 0; // variável ativada dentro da ISR (monitar ISR)float alpha = 0.1; // associado com filtro derivativofloat x; // dados lidos no A/D 0 do Arduínofloat y; // sinal x filtradoint maior, menor; // atualiza em "tempo-real" valores máximos e mínimos (limites Serial Plot)float x1, x2, x3, x4; // valores amostras passadas sinal de entrada xfloat y1, y2, y3, y4; // valores amostras passadas sinal de saída y (sinal filtrado)// Parâmetros do filtro (calculados usando Matlab)float b0 = 0.056448;float b2 = -0.1129;float b4 = 0.056448;float a0 = 1;float a1 = -3.1595;float a2 = 3.7927;float a3 = -2.0826;float a4 = 0.45045;float dy; // derivada primeira do sinal filtradovoid setup() { // put your setup code here, to run once: // Programando a ISR à 50 Hz usando timer 1 cli();//stop interrupts //set timer1 interrupt at 50 Hz TCCR1A = 0; // set entire TCCR1A register to 0 TCCR1B = 0; // same for TCCR1B TCNT1 = 0; //initialize counter value to 0 // set compare match register for 1hz increments OCR1A = 1249; // = (16*10^6) / (50*256) - 1 (must be <65536) // turn on CTC mode TCCR1B |= (1 << WGM12); // Set CS12 bits for 256 prescaler TCCR1B |= (1 << CS12); // enable timer compare interrupt TIMSK1 |= (1 << OCIE1A); pinMode(monitor_isr, OUTPUT); digitalWrite(monitor_isr, LOW); Serial.begin(115200); // setup serial while (!Serial) { ; // Aguarda até que a porta serial esteja pronta - normalmente 10 ms } Serial.println(" "); Serial.println("Monitorando foto-detector: "); // inicializa valores máximos e mínimos maior = 0; menor = 1023; // inicializando amostras atrasadas sinal de entrada x1 = 0; x2 = 0; x3 = 0; x4 = 0; // inicializando amostras atrasas sinal saída filtro y1 = 0; y2 = 0; y3 = 0; y4 = 0; dy = 0; sei();//allow interrupts}ISR(TIMER1_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED) digitalWrite(monitor_isr, HIGH); // Atualiza varíavel x contendo valor lido em A0 x = analogRead(analogPin)*(5.0/1024.0); // converte para faixa 0 á 5 Volts // if (x > maior) maior = x; // if (x < menor) menor = x; // Aplicando fitro Passa-Faixa sobre sinal de entrada x // Saída filtrada em y y = b0*x + b2*x2 + b4*x4 - a1*y1 - a2*y2 - a3*y3 - a4*y4; if (x > maior) maior = x; if (x < menor) menor = x; // derivando sinal filtrado dy = alpha*y + (1.0-alpha)*y1; // não é recomendável enviar dados pela serial dentro de um ISR, mas testando... Serial.print(maior); // value 1 Serial.print(" \t"); Serial.print(menor); // value 2 Serial.print(" \t"); Serial.print(x); // value 3 Serial.print(" \t"); Serial.print(y); // value 4 Serial.print(" \t"); Serial.println(dy); // value 5 // Serial.println(menor); // preparando amostras passadas para próxima chamada da ISR y4 = y3; y3 = y2; y2 = y1; y1 = y; x4 = x3; x3 = x2; x2 = x1; x1 = x; digitalWrite(monitor_isr, LOW);}void loop() { // put your main code here, to run repeatedly: // nada a ser feito aqui}Resultado obtido:

Obs.: durante os primeiros 3/4 da captura mostrada na figura anteiror, o dedo "oscilava" entre o led emissor verde e o foto acoplador. Propositalmente para testar se o filtro digital e derivada estão funcionando. Apenas os últimos segundos do gráfico correspondem ao dedo bloqueando estaticamente o fluxo de luz. E nesta condição, se percebe pelo sinal filtrado que não parece ser possível recuperar a informação esperada.
Através do osciloscópio (conectado ao pino 7, monitor_isr) se comprova que a ISR está sendo executada obdecendo à estilpulada e que ainda "sobra" poder de processamento. Ela levou 1,4 mili-segundos para ser executada, resultando um "duty-cycle" de 7,22%:
Mostrando apenas o sinal bruto e o sinal filtrado com o dedo posicionado de forma estática bloqueando o fluxo luminoso temos:

:o()
Fernando Passold, em 10/10/2024.