Anàlisi de la freqüència de la llum amb un fototransistor i Phyphox

Fa un temps (2021) vaig escriure una entrada sobre la utilització de sensors de llum en el laboratori de Física a secundaria. Dues de les possibilitats de les que parlava era les d’usar una fotoresistència o un fototransistor per estudiar les variacions de lluminositat, i en concret per veure si era possible analitzar les variacions de lluminositat amb el temps de les bombetes com a conseqüència de la variació de la intensitat de corrent que circula per elles ja que les connectem a corrent altern a 50 Hz.

Jo havia aconseguit mesurar aquestes variacions sense cap problema amb els diferents equips EXAO (Experimentació Assistida per Ordinador) dels que he tingut al meu abast. El sensors que utilitzaven aquests equips bé era una fotoresistència o un fototransistor.

Gràfica obtinguda amb la fotoresistència de la placa LittleDoctor. Amb un període de 10 ms la freqüència del parpelleig de la llum que s’obté és de 100 Hz i, per tant, la del corrent altern de 50 Hz
  1. El problema
  2. La solució
  3. El muntatge
  4. El codi
  5. El resultat

El problema

Com explicava a l’entrada dels sensors de llum, només havia pogut mesurar aquestes variacions amb un fototransistor i un Arduino UNO amb el codi més senzill possible i recollint les dades a través del serial port de l’ordinador i després graficant-les , com es veu a sota. Si afegia alguna complicació al codi o utilitzava un ESP32 en lloc de l’arduino ja no aconseguia que el sistema anés suficientment ràpid i es perdien moltes dades pel camí, de manera que el que es mesurava més aviat semblava soroll.

Els data-loggers dels equips EXAO estaven fets amb elements electrònics que no processaven les variacions elèctriques (senyals analògiques) que mesuraven dels diferents sensors i les enviaven directament al programari de la consola o de l’ordinador. D’alguna manera és el que passa amb els arduinos uno, que tenen pins d’entrada analògics purs i si no els distraus amb altres operacions son capaços de transmetre les dades a gran velocitat; per això els puristes de l’electrònica i la instrumentació sempre prefereixen el xip de l’Arduino Uno (ATmega328P) per a lectures analògiques.

Les entrades analògiques dels ESP32 no son pures sinó que son entrades digitals que converteixen les variacions analògiques en uns i zeros, a més que el xip ESP32 és un microprocessador (com els dels telèfons o ordinadors) mentre que l’ATmega328P és un microcontrolador.

Però perquè es necessiten velocitats elevades de presa de dades per veure les variacions d’intensitat de llum que emeten les bombetes?. El corrent elèctric del que disposem és altern a 50 Hz, és a dir, que el voltatge (i la intensitat) puja i baixa en un sentit o en el contrari 100 vegades per segon. Per a poder fer una gràfica d’aquesta variació necessitem com a mínim 1000 valors per segon, el que son molts!

El problema per aconseguir aquesta freqüència de recollida de dades no està en la fotoresistència, ni molt menys en el fototransistor, que és molt més ràpid, sinó com he comentat en el funcionament de les plaques i en la quantitat de processos que els hi demanem, com per exemple que enviïn les dades per Bluetooth a un telèfon mòbil.

La solució

Amb l’ajut del professor d’informàtica Adrián Ramírez i de Gemini (la IA de Google) finalment he arribat a una solució que permet recopilar les dades prou ràpidament amb un ESP32 i enviar-les en blocs a Phyphox de manera que no hi hagi pèrdues pel camí i es vegin les variacions de lluminositat prou bé. Us he de recordar, però, que malgrat el que us estic contant, soc un principiant en programació de manera que entén el que fa el codi que us proposaré però no com ho fa. Per altra banda, encara que siguis principiant, amb una mica de criteri i molta paciència la Intel·ligència Artificial és de gran ajuda amb la programació.

La solució ha passat per aprofitar que el microprocessador de l’ESP32 disposa de dos nuclis, de manera que el codi utilitza un dels nuclis per recollir les dades que li venen del fototransistor i els guarda en un buffer, i de tant en tant (cada deu valors – 80 bytes) l’altre nucli els envia a través de Bluetooth. Blocs de més de deu dades col·lapsarien l’antena del Bluetooth i hauria pèrdua de valors. En aquest últim cas Phyphox aniria empalmant el que li arriba i no es veuria una corba sinusoidal per cap lloc.

A més, en lloc de ficar totes les ordres en l’sketch carregat a l’ESP32, el codi es divideix en dues parts: el programari de Phyphox es carrega directament en l’aplicació i així el codi a instal·lar i córrer al microprocessador és mínim.

El muntatge

El muntatge és el mateix que el de l’entrada Sensors de llum amb Arduino i Phyphox de la que venim parlant, és a dir, es necessita un fototransistor com el TEMT6000 (uns 2 €), una placa de proves (uns 3€) i una placa amb l’ESP32 (uns 5€).

Aquest sensor ja ve preparat per a connectar-se directament a les entrades de les plaques. El pin GND va a terra (GND), el pin VCC a 3,3 o 5 V i el pin OUT va a l’entrada “analògica” 34 en un esp32, com s’intueix en la foto de sota.

Ja he comentat més a dalt que les entrades “analògiques” de l’ESP32 tenen un convertidor analògic-digital (ADC) molt més sorollós que les de l’Arduino UNO. A més, com que l’ESP32 té una antena de ràdio (Bluetooth/Wi-Fi) integrada al mateix xip, cada vegada que transmet un paquet provoca minúscules caigudes de tensió internes que embruten la lectura del sensor de llum.

Per netejar el soroll elèctric al que podria contribuir l’antena de l‟ESP32, ens podem ajudar d’un filtre pas baix. Si a vosaltres encara no us surt una ona sinusoidal prou guapa, col·loqueu un condensador petit (un ceràmic de 100 nF a 1 µF, per exemple) connectat directament entre el pin de sortida del vostre sensor (el que va al pin 34) i el pin GND de la placa. Això actuarà com un amortidor suavitzant els pics de soroll elèctric de l’antena i deixant només la corba pura de la llum. Us he de dir, però, que no ha estat el meu cas i que el condensador ha estat superflu.

El codi

El sensor TEMT6000 no necessita cap llibreria per funcionar però el Bluetooth si, com es veu en el codi de l’sketch a sota, però les llibreries ja estan instal·lades per defecte quan s’instal·len les plaques ESP32 d’Espressif a l’IDE d’Arduino. Si no us recordeu de com instal·lar les plaques ESP32 a l’IDE podeu mirar la informació de l’entrada anterior a aquesta: Sensor de força amb arduinos i Phyphox.

El projecte a carregar a l’ESP32 el podeu obtenir de sketch_luz_paquetes10_optimizado.ino, o bé copiant i empegant el codi de sota.

/*Proyecto para medir variaciones rápidas de luminosidad como las producidas por la bombillas 
conectadas a la red eléctrica a 50 Hz.
Se necesita un fototransistor como el TEMT6000 y una placa ESP32 que dispone de bluetooth.
Este sensor ya está preparado para conectarse directamente a las entradas de las placas.
El pin GND va a tierra (GND), el pin VCC a 3,3 o 5 V y el pin OUT va a la entrada 34.

Los datos obtenidos con este sketch solo se envian por bluetooth, no por el puerto serie.
Para ver los valores en un telefono móvil se ha de tener instalada la aplicación Phyphox
y dentro de ella el experimento "Fototransistor alta frecuencia" que se puede descargar desde
https://experimentaciolliure.com/wp-content/uploads/2026/02/luz_paquetes10.zip
*/

#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

#define SERVICE_UUID "19B10000-E8F2-537E-4F6C-D104768A1214"
#define CHARACTERISTIC_UUID "19B10001-E8F2-537E-4F6C-D104768A1214"

BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
const int ldrPin = 34;

// Reducimos el bloque a 10 para garantizar cero pérdidas por Bluetooth
#define BATCH_SIZE 10

struct SensorBatch {
float tiempo[BATCH_SIZE];
float valor[BATCH_SIZE];
};

QueueHandle_t dataQueue;

class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) { deviceConnected = true; }
void onDisconnect(BLEServer* pServer) { deviceConnected = false; }
};

void adcTask(void *pvParameters) {
SensorBatch batch;
int index = 0;

// Reloj estricto para no perder sincronía
unsigned long nextSampleTime = micros();

for(;;) {
batch.tiempo[index] = micros() / 1000000.0;
batch.valor[index] = (float)analogRead(ldrPin);
index++;

if (index >= BATCH_SIZE) {
// Enviamos a la cola. Si está llena, descarta (pero con la nueva optimización no debería)
xQueueSend(dataQueue, &batch, 0);
index = 0;
}

// Calculamos matemáticamente el siguiente milisegundo exacto
nextSampleTime += 1000;
long waitTime = nextSampleTime - micros();

if (waitTime > 0) {
delayMicroseconds(waitTime);
} else {
nextSampleTime = micros(); // Resincronizar si hubo algún retraso grave
}
}
}

void bleTask(void *pvParameters) {
SensorBatch batch;
for(;;) {
if (xQueueReceive(dataQueue, &batch, portMAX_DELAY)) {
if (deviceConnected) {
// Ahora enviamos 80 bytes, un tamaño mucho más digerible para BLE
pCharacteristic->setValue((uint8_t*)&batch, sizeof(SensorBatch));
pCharacteristic->notify();
}
}
}
}

void setup() {
Serial.begin(115200);

// Aumentamos el tamaño de la sala de espera (cola a 50 bloques)
dataQueue = xQueueCreate(50, sizeof(SensorBatch));

BLEDevice::init("ESP32_Luz");
BLEDevice::setMTU(256); // MTU intermedio seguro

BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());

BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_NOTIFY
);
pCharacteristic->addDescriptor(new BLE2902());

pService->start();
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pServer->getAdvertising()->start();

// Le damos mayor prioridad a la tarea de Bluetooth (2) para vaciar la cola rápido
xTaskCreatePinnedToCore(adcTask, "Lectura", 4096, NULL, 1, NULL, 1);
xTaskCreatePinnedToCore(bleTask, "Envio", 4096, NULL, 2, NULL, 0);
}

void loop() {
vTaskDelete(NULL);
}

Amb el codi de dalt no s’envia l’estructura de l’experiment a Phyphox. Aquesta s’ha de carregar directament a l’aplicació pitjant en el botó més i en Añadir experimento desde un código QR, a continuació. El codi QR el teniu a sota i l’arxiu que es carrega el podeu baixar d’aquí.
 

Una vegada carregat l’experiment el podeu guardar en els experiments de la mateix aplicació per no tenir que acudir al QR cada vegada. Recordeu que per a veure la placa ESP32 per Bluetooth heu de tenir obert al telèfon el propi Bluetooth i la localització.

El resultat

Com es veu en la captura de pantalla de Phyphox, la diferencia de temps entre deu pics de les oscil·lacions de la llum hi és de 0,10 s. La freqüència serà, doncs, f= 1/0,01 = 100 Hz, que és el que volíem obtenir.

La llum que he recollit a l’exemple de la captura de pantalla de Phyphox és la d’una bombeta incandescent. El mateix resultat podem obtenir amb bombetes halògenes, fluorescents o de leds, però no sempre, ja que l’electrònica que acompanya aquests dos últims tipus de bombetes de vegades les fa lluir a freqüències molt molt més elevades (20–40 kHz) amb el que us sortirà un senyal gairebé continu o uns pics que semblen soroll.

Evidentment, el dispositiu serveix també per a mesurar variacions de llum més grosseres i calcular el temps que triga en passar un obstacle pel davant el sensor de llum, per exemple.


Deixa un comentari

Aquest lloc utilitza Akismet per reduir els comentaris brossa. Apreneu com es processen les dades dels comentaris.