V tomto článku se naučíme automaticky zapínat a vypínat světla podle okolního osvětlení.

Princip spočívá v tom, že měříme napětí pomocí ADC na děliči s fotorezistorem a současně měříme napětí na proměnném referenčním děliči napětí. Odpor fotorezistoru závisí na vnějším osvětlení. Osvětlený fotorezistor má malý odpor (stovky Ohmů), fotorezistor ve tmě má odpor okolo 15 kiloOhmů. Referenční dělič nám umožňuje nastavit hranici mezi světlem a tmou.

Spínání světel je pomocí reléového modulu.

Schéma zapojení

Schéma zapojení

schema zapojeni

Prototyp

IMG 20260129 030353

Program

/* Měření na fotoodporu
 * svetlo.c
 * (c) Jirka Chráska 2026, <jirka@lixis.cz>
 */
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "hardware/adc.h"

// pro OLED displej
#include "ssd1306.h"
#include "font_spleen_8x5.h"
#include "font_spleen_16x8a.h"

#define DISPLAY_WIDTH   128
#define DISPLAY_HEIGHT  32
#define I2C_ADDRESS     0x3C
#define I2C_FREQ        400000
#define SLEEPTIME       55
#define SDA_PIN         4
#define SDC_PIN         5
#define I2C             i2c0
ssd1306_t disp;

// nastavení I2C sběrnice
void setup_i2c(void)
{
    // nelze použít i2c_default -- aplikace bude chodit nekorektně (zajímavá chyba)
    i2c_init(I2C, I2C_FREQ);
    gpio_set_function(SDA_PIN, GPIO_FUNC_I2C);
    gpio_set_function(SDC_PIN, GPIO_FUNC_I2C);
    // Pull-up rezistory jsou v displeji, netřeba nastavovat
}

void zapnuti_displeje( void )
{
    ssd1306_init(&disp, DISPLAY_WIDTH, DISPLAY_HEIGHT, I2C_ADDRESS, I2C); // inicializace
    ssd1306_poweron(&disp); // zapnutí displeje
    ssd1306_clear(&disp);   // vymazání displeje
    ssd1306_contrast(&disp,0x50);
    ssd1306_draw_string_with_font(&disp, 0, 0, 1, font_spleen_16x8a, "Osv" "\xec" "tlen" "\xed" ".");
    ssd1306_show(&disp); // zobrazíme písmenka na displeji
}

#define MERENI_PIN      26
#define REFERENCE_PIN   27
#define ADC_INPUT       0
#define REFERENCE_INPUT 1
#define TEMNO           1.3
#define REF_VOLTAGE     3.25f

int main()
{
char buffer[128];
uint16_t raw;
const float conversion_factor = 3.3f / (1<<12);
float reference = 0.0;
float napeti    = 0.0;

    memset(buffer,'\0',128);
    gpio_init(22);
    gpio_set_dir(22,GPIO_OUT);
    gpio_put(22,1);
    // debugování přes USB
    stdio_init_all();
    sleep_ms(1200);
    // inicializace a konfigurace 0LED displeje
    // nastavení displeje SSD1306
    setup_i2c();
    zapnuti_displeje();
    sleep_ms(10);
    // nastavení ADC
    adc_init();
    adc_gpio_init(MERENI_PIN);
    adc_gpio_init(REFERENCE_PIN);
    printf("\nMěření napětí na fotorezistoru.\n");

    // měření osvetleni
    while(1) {
        memset(buffer,'\0',128);
        adc_select_input(ADC_INPUT);
        napeti = adc_read() * REF_VOLTAGE / (1<<12);
        adc_select_input(REFERENCE_INPUT);
        reference = adc_read() * REF_VOLTAGE / (1<<12);
        ssd1306_clear(&disp);
        sprintf(buffer,"S:%5.2fV %s", napeti, napeti > reference ? "temno" : "sv\xectlo");
        ssd1306_draw_string_with_font(&disp,0,0,1, font_spleen_16x8a, buffer);
        sprintf(buffer,"R:%5.2fV",reference);
        ssd1306_draw_string_with_font(&disp,0,16,1, font_spleen_16x8a, buffer);
        ssd1306_show(&disp);
        printf("Napětí fotoodpor: %5.3f V, referenční napětí: %5.3f\n",napeti,reference);
        if( napeti > reference )    {
            gpio_put(22,0);
        } else {
            gpio_put(22,1);
        }
        sleep_ms(500);
    }
    return 0;
}
cmake_minimum_required(VERSION 3.13)

# initialize the SDK based on PICO_SDK_PATH
# note: this must happen before project()
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)

project(osvetleni)

set(CMAKE_C_STANDARD 11)

# initialize the Raspberry Pi Pico SDK
pico_sdk_init()

# rest of your project

add_executable(osvetleni
	svetlo.c
	disp/ssd1306.c
)

target_include_directories(osvetleni
    PUBLIC
        ${CMAKE_CURRENT_LIST_DIR}/disp

)

target_link_libraries(osvetleni
    pico_stdlib
    hardware_i2c
    hardware_adc
)

pico_enable_stdio_usb(osvetleni 1)
pico_enable_stdio_uart(osvetleni 0)

# create map/bin/hex/uf2 file in addition to ELF.
pico_add_extra_outputs(osvetleni)

Zdroje a odkazy