Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
1
P
OLITECHNIKA
Ś
LĄSKA
W
YDZIAŁ
A
UTOMATYKI
, E
LEKTRONIKI
I
I
NFORMATYKI
Projekt z Systemów Mikroprocesorowych
Tytuł: Ultradźwiękowy miernik wysokości poziomu cieczy w
zbiorniku
Autorzy: Pawicki Adrian, Serafiniak Robert
AiR, sem. 5, gr. TI 1
Gliwice, styczeń 2013
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
2
Spis treści
1. Wstęp .............................................................................................................................................. 4
2. Cel i zakres projektu........................................................................................................................ 4
3. Harmonogram................................................................................................................................. 4
4. Aplikacja programowa i sprzętowa................................................................................................ 5
4.1.
Część sprzętowa...................................................................................................................... 5
4.1.1.
Schemat połączeniowy ................................................................................................... 5
4.1.2.
Opis elektroniki............................................................................................................... 6
4.2.
Część programistyczna............................................................................................................ 6
4.2.1.
Oprogramowanie mikrokontrolera................................................................................ 6
4.2.1.1. Kod programu ............................................................................................................. 6
4.2.1.2. Schemat blokowy........................................................................................................ 7
4.2.1.3. Opis działania.............................................................................................................. 7
4.2.1.4. Algorytm przeliczania odległości na czas ................................................................... 8
4.2.2.
Terminal (aplikacja w C#) ............................................................................................... 8
4.2.2.1. Kod aplikacji ................................................................................................................ 8
4.2.2.2. Zrzut ekranu ................................................................................................................ 8
4.2.2.3. Opis działania.............................................................................................................. 9
5. Koszt projektu................................................................................................................................. 9
5.1.
Wycena.................................................................................................................................... 9
5.2.
Poświęcony czas.................................................................................................................... 10
6. Główne problemy ......................................................................................................................... 10
6.1.
Komparator analogowy........................................................................................................ 10
6.2.
Taktowanie mikrokontrolera ............................................................................................... 10
6.3.
Wzmocnienie sygnału........................................................................................................... 11
6.4.
Zakłócenia ultradźwięków.................................................................................................... 12
6.5.
Problem przy przenoszeniu układu na płytkę uniwersalną (przy lutowaniu) .................... 12
6.6.
Przenoszalność kodu............................................................................................................. 12
7. Podsumowanie ............................................................................................................................. 13
8. Pomysł na rozwój.......................................................................................................................... 13
9. Literatura....................................................................................................................................... 13
10.
Załączniki................................................................................................................................... 14
10.1.
Załącznik nr 1 (kod oprogramowanie Atmegi16A) .......................................................... 14
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
3
10.2.
Załącznik nr 2 (kod aplikacji) ............................................................................................ 16
10.3.
Załącznik nr 3 – zdjęcie gotowego układu........................................................................ 21
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
4
1. Wstęp
Celem projektu było stworzenie urządzenia monitorującego wysokość poziomu słupa
cieczy w zaprojektowanym przez nas zbiorniku. Poziom ten miał być monitorowany
za pomocą ultradźwięków, a następnie otrzymane dane miały zostać wysłane za
pomocą komunikacji szeregowej do komputera PC, gdzie byłyby w miarę potrzeby na
bieżąco monitorowane. Za analizę dostarczanych danych (za pomocą portu RS232)
jest odpowiedzialny stworzony przez nas terminal, napisany w języku C#. Terminal
dodatkowo posiada opcję graficznego zobrazowania aktualnie wynoszącej wartości
(w postaci słupa cieczy).
2. Cel i zakres projektu
Naszym celem było stworzenie urządzenia wykorzystywanego do monitorowania
wysokości poziomu cieczy w zbiorniku. Jego skonstruowanie nie było bez podstawne.
Został on stworzony w celu monitorowania poziomu wysokości słupa cieczy (zużytego
oleju silnikowego) w beczkach, jakie są często stosowane m.in. w warsztatach
samochodowych. Owe urządzenie miało służyć do monitorowanie poziomu
napełnienia owego zbiornika, aby w odpowiednim momencie zgłosić potrzebę jego
wymiany na nowy.
Jednak w ramach rozwoju projektu, został znaleziony szereg innych zastosowań. Po
drobnych modyfikacjach może ono być stosowane, jako czujnik cofania w
samochodach lub też alarm domowy, monitorujący czy w danym pomieszczeniu
porusza się jakaś osoba.
3. Harmonogram
Data
Założenia
19-26.11.2012
Skompletowanie niezbędnego sprzętu do wykonanie projektu.
26.11-3.12.2012
Oprogramowanie nadajnika ultradźwięków.
3-10.12.2012
Oprogramowanie odbiornika ultradźwięków.
10-17.12.2012
Szeregowa transmisja danych.
17-24.12.2012
Stworzenie aplikacji umożliwiającej graficzną reprezentację danych w
postaci wykresu.
31.12-7.01.2013
Przeniesienie projektu z uniwersalnej płytki stykowej na płytkę
drukowaną.
7-14.01.2013
Stworzenie prezentacji multimedialnej.
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
5
Projekt został wykonany zgodnie z harmonogramem. Udało się zrealizować wszystkie
cele, które zostały wyznaczone przed podjęciem się wykonania projektu.
4. Aplikacja programowa i sprzętowa
Nasze gotowe urządzenie do monitorowania wysokości poziomu cieczy w zbiorniku
składa się z 2 części – sprzętowej oraz programistycznej.
Część sprzętowa to elektronika, dobór odpowiednich podzespołów (np. rezystorów,
kondensatorów), żeby układ działał jak najsprawniej, natomiast programistyczna
składa się również z dwóch części. Pierwszą z nich jest oprogramowanie
mikrokontrolera (nadawanie/odbieranie ultradźwięków, przesył szeregowy danych),
druga to natomiast stworzenie terminala w C#.
4.1.
Część sprzętowa
4.1.1. Schemat połączeniowy
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
6
4.1.2. Opis elektroniki
Cały układ mikroprocesorowy zdecydowaliśmy się zbudować w oparciu o
mikrokontroler z rodziny AVR – Atmega16A. Wybór był uwarunkowany
tym, że posiadaliśmy już pewną wiedzę dotyczącą programowania AVR.
W celu poprawnego zasilania mikrokontrolera każdy pin zasilający Vcc
został zaopatrzony w kondensator 100nF podciągnięty do masy,
umiejscowiony jak najbliżej mikrokontrolera.
Odbiornik ultradźwiękowy został doposażony w rezystor 100k w celu
eliminacji zakłóceń. Jego wartość została dobrana metodą prób i błędów.
Jest on potrzebny, ponieważ odbiornik podłączamy do komparatora
analogowego, który jest bardzo czuły. Działa on na podstawie
porównywania napięć panujących na nóżkach AIN0 i AIN1. Jeżeli napięcie
na AIN0 jest wyższe, to wówczas odbiornik otrzymał odbitą falę
ultradźwiękową (wykrył przeszkodę).
Nadajnik natomiast generuje nam sygnał prostokątny o częstotliwości
43kHz (sprawdzone na oscyloskopie). W datasheecie nadajnika widnieje
wpis, że wysyła on falę o f = 40kHz. Im bliżej, więc tej częstotliwości, tym
nadajnik generuje lepszy sygnał. Mieścimy się jednak w granicy błędu.
Komunikacja szeregowa została zrealizowana w sposób standardowy, za
pomocą MAX232. Kondensatory elektrolityczne zostały dobrane z pomocą
informacji znalezionych w datasheet, czyli 1uF.
W celu pozbycia się tzw. ‘krzaczków’ wysyłanych RS-em do naszego
terminala zdecydowaliśmy się dołożyć zewnętrzny kwarc 2MHz. W tym
celu również musieliśmy wykorzystać 2 kondensatory ceramiczne 22pF.
Tak zmontowany układ zewnętrznego taktowania musimy być wlutowany
jak najbliżej naszego mikrokontrolera, w celu poprawnego działania.
Dodatkowo układ jest zasilany kablem USB (5V).
Tak zmontowany układ działa poprawnie.
4.2.
Część programistyczna
4.2.1. Oprogramowanie mikrokontrolera
4.2.1.1.
Kod programu
Kod znajduje się w ZAŁĄCZNIKU NR 1
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
7
4.2.1.2.
Schemat blokowy
4.2.1.3.
Opis działania
W celu nadania paczki fal ultradźwiękowych porty PD2 oraz PD3
ustawione są, jako wyjścia. Następnie z użyciem pętli for() na zmianę
doprowadzane jest do nóżek nadajnika w przeciwległej fazie napięcie
wysokie oraz niskie (jeżeli na PD2 jest napięcie wysokie to na PD3 jest
niskie i odwrotnie). Kolejnym krokiem jest wyłączenie nadajnika oraz
chwilowe zwarcie do masy odbiornika w celu eliminacji drgań,
mogących powstać w czasie, gdy nadajnik wysyłał fale. W celu odbioru
fal odbitych włączamy odbiornik oraz aktywujemy timer zliczający
czas, po jakim wróciła fala odbita. Odbiór fal dokonywany jest z
użyciem komparatora analogowego, porównującego napięcia na AIN1
oraz AIN0. W przypadku odbioru fali odbitej napięcie na AIN0 jest
wyższe niż na AIN1, w przeciwnym wypadku nic nie zostało wykryte. W
momencie, gdy AIN0>AIN1(wykryta przeszkoda) timer jest wyłączany,
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
8
następnie przy użyciu rozdzielczości mikrokontrolera oraz prędkości
dźwięku dokonywane jest przeliczanie wartości timera na odległość.
Przeliczona zmienna wysyłana jest poprzez port szeregowy do
komputera PC.
4.2.1.4.
Algorytm przeliczania odległości na czas
Taktowanie mikroprocesora wynosi 2MHz.
Rozdzielczość:
=0.0000005[s]=0.5 [μs]
Zakres timera 16-bit wynosi: [0 - 65 536]
W celu uzyskania czasu przemnażamy wartość timera przez 0.5.
Prędkość dźwięku:
V=340 m/s, jako iż sygnał przebywa drogę podwójną ( do przeszkody i
z powrotem), przyjmujemy 170 m/s.
170[m/s]=1/58,7[cm/us]=0.017[cm/us]
Zgodnie ze wzorem na prędkość, obliczamy drogę:
V=s/t => s=t*V;
Odległość = (Wartość_Timera*0.5)/58.7;
4.2.2. Terminal (aplikacja w C#)
4.2.2.1.
Kod aplikacji
Kod aplikacji znajduje się w ZAŁĄCZNIKU NR 2
4.2.2.2.
Zrzut ekranu
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
9
4.2.2.3.
Opis działania
Aplikacja oferuję użytkownikowi podgląd odbieranych danych z
mikrokontrolera. Ponadto użytkownik ma możliwość podglądu
odbieranych danych w postaci graficznej(wykres słupkowy).
Użytkownik ma również możliwość doboru parametrów dotyczących
transferu danych takich jak: prędkości, wybór portu, ilość bitów
danych, bit stopu oraz bit parzystości.
W celu połączenia aplikacji z mikrokontrolerem przez port szeregowy
korzystamy z biblioteki System.IO.Ports.
Dane są pobierana przy wykorzystaniu metody ReadLine(), która
pozwala na pobranie ciągu znaków do momentu napotkania znaku
końca linii („\n”). Następnie dane są wyświetlane w TextBoxie oraz
konwertowane na format typu Int.
Przekonwertowana zmienna wysyłana jest do funkcji wyrysowującej
wykres. W celu rysowania wykresu słupkowego korzystamy z biblioteki
ZedGraph. Oferuję Ona zestaw gotowych metod do wyrysowywania
wykresów. Cały proces powtarza się tak długo aż zostanie urwane
połączenie z mikrokontrolerem.
5. Koszt projektu
5.1.
Wycena
Przedmiot
Cena
Atmega16A
12,29
MAX232
1,90
Nadajnik ultradźwiękowy
6,00
Odbiornik ultradźwiękowy
6,00
Kwarc 2MHz
1,15
2x kondensator ceramiczny 22pF
0,20
Rezystor 100k
0.05
4x kondensator elektrolityczny 1uF
0,40
Gniazdo DB9
0,70
Płytka uniwersalna
10,00
SUMA
38,69
Całkowity koszt zbudowania urządzenia, wraz z płytką uniwersalną, do której
zostały wlutowane wszystkie elementy wyniósł 38,69zł.
Jest to stosunkowo niska cena. Została ona osiągnięta dzięki wykorzystaniu
najtańszych czujników ultradźwiękowych.
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
10
Dodatkowo w celu zmniejszenia kosztów produkcji warto byłoby się zastanowić
nad wykorzystaniem tańszego mikrokontrolera (np. atmega8) oraz nad
wytrawianiem własnych płytek. Widzimy, bowiem, że kupno płytki uniwersalnej
bardzo mocno podnosiło nam koszt wykonania całego projektu.
5.2.
Poświęcony czas
Pomimo pozornej prostoty projektu, czas, który został poświęcony nad jego
wykonaniem jest naprawdę spory. Jest on rzędu, co najmniej kilkudziesięciu
godzin ciężkiej pracy. Jest to głównie związane z szeregiem problemów, które
napotkaliśmy podczas realizacji projektu. Na te temat zostanie poświęcony
osobny dział.
6. Główne problemy
6.1.
Komparator analogowy
W celu odbioru fal ultradźwiękowych został wykorzystany komparator
analogowy, porównujące napięcia na AIN1 oraz AIN0. Ze względu na bardzo czułe
zachowanie się komparatora na jakiegokolwiek rodzaju zakłócenia wystąpił
problem w rozróżnieniu czy odbiornik odebrał falę odbitą czy też nastąpiło
zakłócenie. W celu wyeliminowanie problemu pomiędzy nóżki odbiornika został
wprowadzony rezystor o oporze 100k. Dobór wartości rezystora odbył się na
zasadzie prób i błędów. Ważne było, aby przy doborze rezystancji, nie dobrać
rezystora o zbyt dużym oporze mogącym spowodować, iż komparator nie wykryję
odebranej fali ultradźwiękowej. Wprowadzenie rezystora rozwiązało powyższy
problem.
6.2.
Taktowanie mikrokontrolera
Przy początkowych testach dotyczących przesyłania informacji portem
szeregowym z naszego urządzenia na komputer PC okazało się, że czasem w
terminalu były wyświetlane tzw. ‘krzaczki’ – czyli losowe znaki, nie mające
większego sensu. Po przewertowaniu forów internetowych w celu znalezienia
problemu, okazało się, że winą może być taktowanie. Tzn. sposobem rozwiązania
tego problemu było dołożenie zewnętrznego generatora kwarcowego, który
generuje stabilniejsze źródło sygnału – w naszym przypadku kwarcu 2MHz.
Po jego dołożeniu do układu problem znikł.
Należy jednak zaznaczyć, że kwarc musi być zamontowany możliwie blisko
mikrokontrolera, jest to związane z długością ścieżek, w praktyce odległość ta nie
powinna być większa niż 3cm.
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
11
6.3.
Wzmocnienie sygnału
W celu zwiększenia zasięgu naszego układu staraliśmy się wzmocnić napięcie
podawane na nadajnik ultradźwiękowy. Bez wzmacniacza jego zasięg wynosi
(obecnie) ok. 45 cm. (dokładność +- 1cm.).
W tym celu obraliśmy dwie drogi:
Wzmocnienie sygnału za pomocą układu MAX232 – 2 krotne wzmocnienie
napięcia
W tak zmontowanym wzmacniaczu, nasz układ zwiększył swój zasięg do
ok. 80 cm. Jednak wówczas nie radził on sobie z zakresem 0 – 30cm.
Wzmocnienie z wykorzystaniem wzmacniacza operacyjnego NE5532
W tym przypadku, napięcie wzrosło ok. 2.5 razy. Jednak pomimo tego
sygnał nie został wzmocniony, tzn. układy wykrywał przeszkody z zakresu
0 -30cm. Zauważyliśmy natomiast znaczną poprawę stabilności pracy
naszego urządzenia – brak losowych zakłóceń, zwracających błędne dane.
Problem małego zasięgu przy wykorzystaniu NE5532 nie został
rozwiązany.
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
12
Na podstawie powyższych doświadczeń zrezygnowaliśmy z dokładania
wzmacniacza do naszego urządzenia końcowego. Musimy się zadowolić zasięgiem
ok. 45cm. Nie jesteśmy również w stanie wyjaśnić, dlaczego stosując wzmacniacze
operacyjne nie otrzymaliśmy oczekiwanych efektów. Więc z braku czasu,
zrezygnowaliśmy ostatecznie ze wzmocnienia sygnału.
6.4.
Zakłócenia ultradźwięków
Podczas testowania wyżej omówionego układu wystąpił problem związany z
odbiorem fal ultradźwiękowych. W niektórych pomieszczeniach dochodziło do
odbioru fal, pomimo iż nie były to fale, które zostały wygenerowane przez nasz
nadajnik i powróciły w skutek odbicia się od przeszkody. W celu znalezienia źródła
problemu, obserwowaliśmy zachowanie odbiornika w momencie, kiedy nadajnik
był odłączony. Wykazało to, iż źródłem problemu nie jest nasz nadajnik. Problem
nie został rozwiązany po mimo wielu prób. Źródłem takiego zachowania
odbiornika, może być odbiór fal generowanych przez inne urządzenia znajdujące
się w pomieszczeniu. Powyższy wniosek nie został udowodniony.
6.5.
Problem przy przenoszeniu układu na płytkę uniwersalną (przy lutowaniu)
Podczas przenoszenia układu z uniwersalnej płytki stykowej na płytkę,
umożliwiającą zlutowanie ze sobą konkretnego sprzętu elektronicznego pojawił
się problem z szeregową transmisją danych. Tzn. podczas lutowania
prawdopodobnie uszkodzeniu uległ MAX232, przez co układ nie działał
poprawnie. Dodatkowo, gdy do urządzenia zostało doprowadzone napięcie,
MAX232 przegrzał się do bardzo wysokiej temperatury (wręcz parzył) oraz zaczął
wydobywać się z niego dym.
Problem został rozwiązany poprzez wprowadzenie nowego Max232, jednak było
to bardzo problematyczne, gdyż posiadając jedynie lutownicę grotową bardzo
ciężko było odlutować stary element (łącznie 16 nóżek) oraz wstawić w to miejsce
nowy.
6.6.
Przenoszalność kodu
Nie wiedzieć, dlaczego, nasz kod działa jedynie na jednej atmedze16a. Układ był
montowany w oparciu o 3 inne atmegi16a oraz 8 i 32. Problem mógł okazać się
włączony JTAG, natomiast w każdym mikrokontrolerze został on przez nas
wyłączony.
Powodem może być jakaś zmiana producenta, ponieważ układ obecnie działa w
oparciu o atmege16a pochodzącą sprzed ok. 2 lat.
Jednak również (już po skonstruowaniu urządzenia) doszliśmy do wniosku, że
problemem mógł być po prostu zły dobór rezystora na odbiorniku dla
pozostałych mikrokontrolerów z rodziny AVR !!!
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
13
7. Podsumowanie
Wszystkie cele postawione podczas rozpoczęcia projektu zostały zrealizowane. Prace
przebiegały zgodnie z napisanym harmonogramem, który został również w pełni
wykonany. Nasz miernik wysokości poziomu słupa cieczy został przetestowany w
zaprojektowanym przez nas zbiorniku 30 litrowym, o wysokości ok. 40cm. Jego
działanie jest poprawne, zwraca dobre wyniki.
8. Pomysł na rozwój
Przede wszystkim chcielibyśmy stabilnie wzmocnić działanie naszego układu, żeby
poprawnie działał dla odległości 0:150cm. Wówczas zakres jego zastosowanie będzie
znacznie większy i mógłby zostać stosowany z powodzeniem w dużych zbiorniach
stosowanych jak wcześniej wspominaliśmy przy przechowywaniu m.in. zużytego oleju
silnikowego. Dodatkowo pragnęlibyśmy udoskonalić nasz terminal oraz z czasem
udostępniać go darmowo dla osób, które zakupiłyby nasze urządzenie.
Kolejnym pomysłem jest podmiana czujników na droższe, wodoodporne.
9. Literatura
M. Kardaś: Mikrokontrolery AVR. Język C. Podstawy programowania.
Forum internetowe:
www.elektroda.pl
http://hobby.abxyz.bplaced.net
http://www.forbot.pl/forum/topics20/programowanie-port-szeregowy-i-
interfejs-usart-czyli-komunikacja-mikrokontrolera-z-komputerem-
vt6118.htm
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
14
10. Załączniki
10.1.
Załącznik nr 1 (kod oprogramowanie Atmegi16A)
/*
* Sonar_beta.c
*
* Created: 2012-12-27 11:45:06
* Author: Pawicki,Serafiniak
*/
//definicja prędkości transferu danych
#define BAUD 2400
//definicja taktowania
#define F_CPU 2000000
//
obliczenie UBRR
#define UBRR F_CPU/BAUD/16-1
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
// Inicjuje port szeregowy AVRa
void USART_init(unsigned int myubrr)
{
// Ustala prędkość transmisji
UBRRH = (unsigned char)(myubrr>>8);
UBRRL = (unsigned char)myubrr;
// Włącza nadajnika
UCSRB = (1<<TXEN);
// Format ramki: 8 bitów danych, 1 bit stopu, brak bitu parzystości
UCSRC = (1<<URSEL)|(3<<UCSZ0);
}
// Wysyła znak do portu szeregowego
static int USART_Transmit(char znak, FILE *stream)
{
while(!(UCSRA & (1<<UDRE)));
UDR = znak;
return 0;
}
//Tworzy strumienia danych o nazwie 'mystdout' połączony z funkcją 'USART_Transmit'
static FILE mystdout = FDEV_SETUP_STREAM(USART_Transmit, NULL, _FDEV_SETUP_WRITE);
int main(void)
{
//zmienna wykorzystywana przy nadawaniu fal
int i=0;
//zmienna, do której przypisujemy wartość timera
int czas=0;
//zmienna przechowująca wartość przeliczonego czasu na odległość
int pomiar=0;
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
15
// Inicjalizuje port szeregowy AVRa
USART_init(UBRR);
// Przekierowuje standardowe wyjście do 'mystdout'
stdout = &mystdout;
//globalne przerwania
sei();
//ODBIORNIK KONFIGURACJA(ustawiamy PD3 jako wyjście, ustawiamy niski stan napięcia)
DDRB |= (1<<PB3);
PORTB &= ~(1 << PB3);
// NADAJNIK KONFIGURACJA(PD2, PD3 jako wyjście, PD2 wysokie napięcie, PD3 niskie napięcie)
DDRD |= (1<<PD2);
PORTD |= (1<<PD2);
DDRD |= (1<<PD3);
PORTD &= ~(1<<PD3);
while(1)
{
//ustawiamy stan wysoki na jednej z nóżcek nadajnika w celu nadawania sygnału
PORTD |= (1<<PD2);
//nadajemy fale
for(i=0;i<10000;i++)
PORTD^=((1<<PD3)|(1<<PD2));
//wyłączenie nadajnika
PORTD &=~((1<<PD2)|(1<<PD3));
_delay_us(5);
//zwarcie do masy odbiornika, w celu zaniku drgań
DDRB |= (1<<PB2);
PORTB &= ~(1<<PB2);
_delay_us(5);
//włączenie odbiornika
DDRB &= ~(1<<PB2);
//włączenie timera 16bitowego
TCCR1B |= (1 << CS10);
//pętla oczekująca na powrót echa, czekamy do momentu aż timer zlicze 65tys (jest to około
0,03sekundy)
while(TCNT1<65000)
{
//jeśli AIN0>AIN1, to odebrano sygnał odbity
if( ACSR & (1<<ACO) )
{
//przypisanie wartości timera do zmiennej
czas=TCNT1;
//wyłączamy timer
TCCR1B &= ~(1 << CS10);
//przerwanie pętli
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
16
break;
}
}
//jeżeli timer się przepełnił (nic nie zostało wykryte) to wyłączamy timer
if(TCNT1 >= 65000)
{
TCCR1B &= ~(1 << CS10);
czas=0;
}
//przeliczamy uzyskany czas na odległość(algorytm przeliczania został wytłumaczony w
raporcie)
pomiar=(czas/2)/58,7;
//zabezpiczenie przed zakłóceniami ( pomiar nie może przyjąć wartości ujemnej )
if(pomiar > 0){
if(TCNT1 < 65000)
{
//odjęcie uzyskanej wartości od maksymalnej wysokości zbiornika
pomiar=38-pomiar;
//wysyłamy dane poprzez port szeregowy
printf("%d\n",pomiar);
_delay_ms(200);
}
}
//zerujemy czas oraz wartość timera
czas=0;
TCNT1=0;
}
}
10.2. Załącznik nr 2 (kod aplikacji)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports
;
//biblioteka do obsługi RS232
using ZedGraph;
//biblioteka służąca do rysowania wykresów
namespace Terminal
{
public partial class Form1 : Form
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
17
{
//definicja zmiennej port
SerialPort port;
//definicja delegatu
delegate void Delegat1();
//zmienna typu delegat
Delegat1 moj_del1;
//zlicza ilość zmiennych wyświetlonych na ekranie
Int32 licznik;
//zmienna przechowująca zawartość pomiaru
int numVal=-1;
//
zmienna przechowująca odebrany ciąg znaków, używana do konwersji na Inta
string znak;
//potrzebna do wyrysowania wysokości baru
double[] doubleVal= { 0 };
//potrzebne tylko i wyłącznie do ustawienia skalowania wykresu
int licznik2 = 0;
public Form1()
{
InitializeComponent();
//inicjalizacja zmiennej port z domyślnymi wartościami
port = new SerialPort();
//ustawienie timeoutów aby program się nie wieszał
port.ReadTimeout = 500;
port.WriteTimeout = 500;
Opcje.Enter += new EventHandler(Opcje_Enter);
//event od przychodzących danych
port.DataReceived += new SerialDataReceivedEventHandler(DataRecievedHandler);
//inicjalizacja delegatu
moj_del1 = new Delegat1(WpiszOdebrane);
}
//dopisywanie odebranego stringu do textboxa
private void WpiszOdebrane()
{
Wyswietl(OknoWiadomosci, port.ReadLine(), System.Drawing.Color.Blue);
}
//wywołanie delegata po wykryciu przychodzącej wiadomości
private void DataRecievedHandler(object sender, SerialDataReceivedEventArgs e)
{
//Invoke pozwala na bezpieczne wywołanie funkcji delegatu, bez zakłócenia pracy innych wątków
OknoWiadomosci.Invoke(moj_del1);
}
void Opcje_Enter(object sender, EventArgs e)
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
18
{
//aktualizacja list
this.ListaPortow.Items.Clear();
this.ListaParzystosci.Items.Clear();
this.ListaStopu.Items.Clear();
foreach (String s in SerialPort.GetPortNames()) this.ListaPortow.Items.Add(s);
foreach (String s in Enum.GetNames(typeof(Parity))) this.ListaParzystosci.Items.Add(s);
foreach (String s in Enum.GetNames(typeof(StopBits))) this.ListaStopu.Items.Add(s);
//aktualizacja nazw
ListaPortow.Text = port.PortName.ToString();
ListaPredkosci.Text = port.BaudRate.ToString();
ListaDanych.Text = port.DataBits.ToString();
ListaParzystosci.Text = port.Parity.ToString();
ListaStopu.Text = port.StopBits.ToString();
}
private void Wyswietl(System.Windows.Forms.RichTextBox RichTextBox, string Text, System.Drawing.Color
Color)
{
try
{
znak = Text;
//konwersja na inta
numVal = Convert.ToInt32(znak);
//w celu wyrysowania wykresu słupkowego należy inta przypisać zmiennej double[] (metoda rysująca
słupek, nie przyjmuje innych wartości)
doubleVal[0] = numVal;
//wyrysowanie wykresu
CreateGraph(zedGraphControl1, doubleVal);
}
catch (FormatException e)
{
Console.WriteLine("Input string is not a sequence of digits.");
}
catch (OverflowException e)
{
Console.WriteLine("The number cannot fit in an Int32.");
}
finally
{
licznik++;
var StartIndex = RichTextBox.TextLength;
RichTextBox.AppendText(Text);
RichTextBox.AppendText("\n");
var EndIndex = RichTextBox.TextLength;
RichTextBox.Select(StartIndex, EndIndex - StartIndex);
RichTextBox.SelectionColor = Color;
//co 10 wyświetlonych informacji, czyścimy TextBoxa
if (licznik > 10)
{
OknoWiadomosci.Clear();
licznik = 0;
}
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
19
}
}
private void Polaczenie_Click(object sender, EventArgs e)
{
//sprawdzamy czy połączenie jest aktywne
if (port.IsOpen)
{
Polaczenie.BackColor = System.Drawing.Color.Red;
port.Close();
LabelPolaczenie.Text = "Brak połączenia";
Wyswietl(OknoWiadomosci, "\nZakończono połączenie z " + port.PortName + "\n",
System.Drawing.Color.Orange);
}
else
{
//zabezpieczenie na wypadek błędu
try
{
//przypisanie do portu parametrów z opcji
port.PortName = this.ListaPortow.Text;
port.BaudRate = Int32.Parse(this.ListaPredkosci.Text);
port.DataBits = Int32.Parse(this.ListaDanych.Text);
port.Parity = (Parity)Enum.Parse(typeof(Parity), this.ListaParzystosci.Text);
port.StopBits = (StopBits)Enum.Parse(typeof(StopBits), this.ListaStopu.Text);
//uruchamiamy port
port.Open();
//po uruchomieniu zmieniamy elementy graficzne interfejsu
Polaczenie.BackColor = System.Drawing.Color.Green;
LabelPolaczenie.Text = "Aktywne połączenie (port:" + port.PortName.ToString() + ", prędkość: " +
port.BaudRate.ToString() + ", bity danych: " +
port.DataBits.ToString() + "\n bity stopu: " + port.StopBits.ToString() + ", parzystość: " +
port.Parity.ToString() + ")";
Wyswietl(OknoWiadomosci, "Rozpoczęto połączenie z " + port.PortName + "\n",
System.Drawing.Color.Orange);
}
//przechwytujemy błąd i wyświetlamy
catch (Exception exc)
{
MessageBox.Show("Błąd połączenia:\n" + exc.Message);
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
CreateGraph(zedGraphControl1, null);
}
//funckcja wyrysowująca wykres słupkowy
private void CreateGraph(ZedGraphControl zg1, double[] y)
{
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
20
//czyszczenie wykresu, w celu zaznaczenia nowych danych
zg1.GraphPane.CurveList.Clear();
//wysokość zbiornika
double[] z = { 38 };
GraphPane myPane = zg1.GraphPane;
myPane.Title.Text = "Zbiornik";
myPane.XAxis.Title.Text = "";
myPane.YAxis.Title.Text = "Wysokość";
//pozwalamy wyskalować tylko raz wykres, zaraz przy włączeniu programu. Z każdym kolejnym
pomiarem oś ma pozostać niezmieniona
if (licznik2 == 0)
{
zedGraphControl1.GraphPane.XAxis.Scale.MaxAuto = true;
zedGraphControl1.GraphPane.XAxis.Scale.MinAuto = true;
licznik2 = 1;
}
else
{
zedGraphControl1.GraphPane.XAxis.Scale.MaxAuto = false;
zedGraphControl1.GraphPane.XAxis.Scale.MinAuto = false;
}
//słupek max wysokości zbiornika
BarItem myBar2 = myPane.AddBar("", null, z, Color.Blue);
//słupek wartości obecniej wysokości zbiornika
BarItem myBar = myPane.AddBar("", null, y, Color.Red);
myBar.Bar.Fill = new Fill(Color.Red, Color.White, Color.Red);
//Wypełnienie osi i tła
myPane.Chart.Fill = new Fill(Color.White, Color.FromArgb(255, 255, 166), 90F);
myPane.Fill = new Fill(Color.FromArgb(250, 250, 255));
//dopasowanie osi do wyświetlanych danych
zg1.AxisChange();
zg1.Refresh();
}
}
}
Ultradźwiękowy miernik wysokości poziomu cieczy w zbiorniku
21
10.3. Załącznik nr 3 – zdjęcie gotowego układu