Menu Zamknij

Kod asembler do obsługi czujnika temperatury w pompie ciepła

Aby napisać kod w asemblerze do obsługi czujnika temperatury w pompie ciepła, musimy znać konkretny mikrokontroler lub mikroprocesor, który jest używany w systemie. W tym przykładzie założymy, że używamy popularnego mikrokontrolera AVR (np. ATmega328P, który jest używany w Arduino Uno).

Załóżmy, że czujnik temperatury to NTC (termistor), który jest podłączony do wejścia ADC (analogowo-cyfrowego) mikrokontrolera. Poniżej znajduje się przykładowy kod w asemblerze AVR do odczytu wartości z ADC i przesyłania wyniku przez interfejs USART:

.include "m328pdef.inc"

; Konfiguracja rejestrów
.equ USART_BAUD_RATE, 9600
.equ F_CPU, 16000000

; Inicjalizacja ADC
init_adc:
    ldi r16, (1<<REFS0) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0) ; Ustawienia ADC
    sts ADMUX, r16
    ldi r16, (1<<ADEN) | (1<<ADSC) ; Włącz ADC i rozpocznij konwersję
    sts ADCSRA, r16
    ret

; Inicjalizacja USART
init_usart:
    ldi r16, high(F_CPU/16/USART_BAUD_RATE-1)
    sts UBRR0H, r16
    ldi r16, low(F_CPU/16/USART_BAUD_RATE-1)
    sts UBRR0L, r16
    ldi r16, (1<<TXEN0)
    sts UCSR0B, r16
    ldi r16, (1<<UCSZ01) | (1<<UCSZ00)
    sts UCSR0C, r16
    ret

; Wysyłanie bajtu przez USART
send_byte:
    sts UDR0, r16
    sbis UCSR0A, UDRE0
    rjmp send_byte
    ret

; Program główny
main:
    rcall init_adc
    rcall init_usart

loop:
    lds r16, ADCL
    lds r17, ADCH
    rcall send_byte
    ldi r30, 0x0A ; Wysyłanie znaku nowej linii (LF)
    rcall send_byte
    ldi r30, 0x0D ; Wysyłanie znaku powrotu kursora (CR)
    rcall send_byte
    rcall delay_1s
    rjmp loop

; Opóźnienie 1 sekundy
delay_1s:
    ldi r18, 6
    ldi r19, 19
    ldi r20, 174
delay_loop:
    dec r20
    brne delay_loop
    dec r19
    brne delay_loop
    dec r18
    brne delay_loop
    ret


Ten kod inicjalizuje ADC i USART, a następnie w pętli odczytuje wartość z ADC i wysyła ją przez interfejs USART.

; Odczyt wartości ADC
read_adc:
    lds r16, ADCSRA
    ori r16, (1<<ADSC)
    sts ADCSRA, r16
    adc_wait:
        lds r16, ADCSRA
        sbrs r16, ADSC
        rjmp adc_wait
    lds r16, ADCL
    lds r17, ADCH
    ret

; Liniowa interpolacja temperatury
; r16 = ADC_LOW, r17 = ADC_HIGH
; Wartości interpolacji muszą być dostosowane do konkretnego termistora
interpolate_temperature:
    ; Wartości przykładowe dla interpolacji
    ldi r18, 25 ; T1 (temperatura 1)
    ldi r19, 100 ; ADC1 (wartość ADC dla T1)
    ldi r20, 50 ; T2 (temperatura 2)
    ldi r21, 200 ; ADC2 (wartość ADC dla T2)

    ; Obliczanie różnicy temperatury (dT)
    sub r20, r18

    ; Obliczanie różnicy wartości ADC (dADC)
    sub r21, r19

    ; Obliczanie współczynnika k = dT / dADC
    ; Zakładając, że różnice są małe, pomijamy dzielenie
    ; Aby zwiększyć dokładność, można użyć algorytmu dzielenia

    ; Obliczanie wartości ADC - ADC1
    sub r16, r19
    sbc r17, r1

    ; Obliczanie temperatury: T = T1 + k * (ADC - ADC1)
    ; Ponieważ pomijamy dzielenie, obliczamy T = T1 + (ADC - ADC1)
    add r16, r18
    adc r17, r1
    ret

; Program główny
main:
    rcall init_adc
    rcall init_usart

loop:
    rcall read_adc
    rcall interpolate_temperature

    ; Wysyłanie temperatury jako liczby dziesiętnej
    rcall send_temperature
    rcall delay_1s
    rjmp loop

; Wysyłanie temperatury jako liczby dziesiętnej
send_temperature:
    ; Zakładając, że temperatura jest poniżej 100 stopni
    ; Wartość setek (tylko dla temperatury >= 100 stopni)
    ; ldi r18, 0
    ; rcall send_decimal_digit

    ; Wartość dziesiątek
    ldi r18, 10
send_tens:
    cp r16, r18
    brlo send_units
    subi r16, 10
    inc r19
    rjmp send_tens
send_units:
    ; Wysyłanie dziesiątek
    rcall send_decimal_digit

    ; Wysyłanie jednostek
    mov r19, r16
    rcall send_decimal_digit

    ret

; 


; Wysyłanie cyfry dziesiętnej
send_decimal_digit:
    ; Konwersja cyfry dziesiętnej na znak ASCII
    add r19, 0x30

    ; Wysyłanie znaku przez USART
    mov r16, r19
    rcall send_byte

    ret

; Opóźnienie 1 sekundy
delay_1s:
    ldi r18, 6
    ldi r19, 19
    ldi r20, 174
delay_loop:
    dec r20
    brne delay_loop
    dec r19
    brne delay_loop
    dec r18
    brne delay_loop
    ret

Ten kod implementuje funkcję do wysyłania cyfry dziesiętnej przez interfejs USART oraz dodaje opóźnienie 1 sekundy między odczytami temperatury. Wynikowa temperatura zostaje wysłana jako liczba dziesiętna w postaci znaków ASCII.

Warto zauważyć, że powyższy kod jest uproszczonym przykładem i może wymagać modyfikacji oraz dodatkowych optymalizacji w zależności od konkretnego zastosowania i wymagań systemu. Przed wdrożeniem tego kodu w rzeczywistym systemie pompy ciepła, należy przeprowadzić testy i dostosować parametry, takie jak wartości interpolacji, do używanego czujnika temperatury.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *