Individální projekty MPOA

Mikroprocesory s architekturou ARM

Uživatelské nástroje

Nástroje pro tento web


2015:sam3x-clock

Hodiny s teploměrem

Zadání projektu

Navrhněte hodiny s funkcí měření teploty. Implementujte automatické řízení jasu displeje dle okolního osvětlení. Použijte mikrokontrolér Atmel ATSAM3X8E a vhodný obvod hodin reálného času.

Použité zařízení (Hardware)

Pro projekt byla použita základní deska Arduino DUE s procesorem Atmel AT91SAM3X8E jako periferie byl použit display WC1602A teplotní čidla Dallas DS18B20, fotoodpor VT43N1, Spínací tranzistor IRFZ44NS a obvod reálního času DS3231. Samozřejmostí je nutnost programovacího kabelu s microUSB. Všechny periferie byly propojeny pomocí nepájivého kontaktního pole a propojovacích vodičů. Main deska Arduino DUE je vybaveno zmíněným procesorem Atmel ATSAM3X8E s ARm Cortex-M3. Jedná se o jednoduchý ARM procesor s 54 digitálními piny z nich 12 lze využít pro řízení PWM, 12 jako analogový vstup, až 4 sériové porty, USB-OTG, dvěma DAC převodníky, aj. o taktu 84MHz.

 Náhled na zapojení všech periferií k procesorové desce

 obr.1 Náhled na zapojení všech periferií k procesorové desce 

Popis funkce

Fotoodpor slouží ke snímání intezity okolního jasu v zapojení jako dělič z napájecího napětí jehož střed je přiveden na analogový vstup procesoru. Tranzostor IRFZ44NS je výkonový spínací prvek pro podsvícení displeje, jehož Gate je řízena signálem PWM z procesoru. LCD display je schopen najednou zobrazit 32 znaků a slouží jako výstupní zařízení celého projektu. Na předchozím obrázku je ještě vidět potenciometr, který nastavuje kontrast displeje. Teplotní čidla Dallas DS18B20 nají výhodu, že lze je uplatnit paralelně s využitím pouze dvou vodičů, zde však je použito standardní tří-vodičové napájení, kde jeden vodič je datový, přivedený na pin procesoru z obou čidel najednou. Obvod reálného času má výhodu využití záložní baterie a proto když odpojíme napájení nemusíme čas znovu nastavovat. Data do procesoru se dostanou pomocí implementované sběrnice IIC na desce RTC.Na následujícím obrázku je vyobrazeno blokové schéma celého zapojení.

 Blokové schéma zapojení projektu

obr.2 Blokové schéma zapojení projektu 

Demo

Pro realizaci projektu bylo využito prostředí eclipse. Za pomocí knihoven pro Arduino a knihoven pro periferie stažené z GitHubu byl vytvořen projekt MPOA v prostředím eclipse ve verzi Kepler c++.

Projekt byl vytvářen po sekcích ,které ospovídali připojení vždy jedné periferie, tedy k CPU desce byl připojen diplej a vyzkoušeno zobrazení jednoduchého text. Dále byla připojena periferie RTC a zobrazeno datum s časem na dipleji. Další fází byly teplotní čidla, fotoodpor a PWM řízení jasu displeje.

V následujícím videu je nahráno kompletní zobrazení displeje s přepínáním zaznamenané maximální a minimální teploty spolu s datumem:

V tutaj části je prezentován zdrojový kód.

//Na displeju zobrazi teplotu, cas a datum
#include "MPOA_DUE.h"
#include "DallasTemperature.h"//Teplota
#include <OneWire.h>		  //Teplota
#include <LiquidCrystal.h>	  //LCD
#include <Wire.h>			  //RTC
//BEZ knihovny DS1307/DS3231!!!
 
// Data wires is plugged into pins:
#define ONE_WIRE_BUS 2				//Teplota
#define DS3231_I2C_ADDRESS 0x68		//RTC
 
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
//LCD piny
LiquidCrystal lcd(22, 24, 26, 28, 30, 32);
 
float teplota0;//sem se ulozi prectena teplota z Dallasu
float teplota0M;//maximum teploty0
float teplota0m;//minimum teploty0
float teplota1;//sem se ulozi prectena teplota z Dallasu
float teplota1M;//maximum teploty1
float teplota1m;//minimum teploty1
String teploty;//string na vypis teplot+maxim+minim
char LCD_teploty[75];//pomocný char na zobrazení teplot
char LCD_Tout[17];//tohle se primo zobrazi na displeji
unsigned long previousMillis = 500;//pomocna neblokujici cekani
const long interval = 200;//pomocna na nebkokujici cekani
byte mov = 0;//posuv
int ledPin = 3;    // LCD_LED (PWM) connected to digital pin 3
 
void first_read_sensors()
{//první čtení z čidel po zapnutí - do maxima a minima se uloží aktuální teplota
	sensors.requestTemperatures();
	//DALLAS1
	teplota1 = sensors.getTempCByIndex(1);
	//DALLAS0
	teplota0 = sensors.getTempCByIndex(0);
	teplota1M=teplota1;
	if(-127<teplota1m)
		teplota1m=teplota1;
	teplota0M = teplota0;
	if(-127<teplota0m)
		teplota0m = teplota0;
}
 
void read_sensors()
{//kromě prvniho kazde cteni z cidel
	sensors.requestTemperatures();
	//DALLAS1
	teplota1 = sensors.getTempCByIndex(1);
	//DALLAS0
	teplota0 = sensors.getTempCByIndex(0);
}
 
//RTC
byte decToBcd(byte val)
{// Convert normal decimal numbers to binary coded decimal
  return( (val/10*16) + (val%10) );
}
 
byte bcdToDec(byte val)
{// Convert binary coded decimal to normal decimal numbers
  return( (val/16*10) + (val%16) );
}
 
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year)
{  // sets time and date data to DS3231
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x00); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}
void readDS3231time(byte *second,byte *minute,byte *hour,byte *dayOfWeek,byte *dayOfMonth,byte *month,byte *year)
{//cteni z hodin
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}
 
void set_time()
{//nastaveni casu
	// set the initial time here:
	// DS3231 seconds, minutes, hours, day, date, month, year
	 setDS3231time(04,57,22,4,26,11,15);
}
 
//The setup function is called once at startup of the sketch
void setup()
{
	  Serial.begin(9600);
	  sensors.begin(); // IC Default 9 bit.Dallas
	  Wire.begin(); //DS3231
	  lcd.begin(16, 2);//LCD 16*2
	  //set_time();//Aktivuje nastaveni casu
	  delay(500);
	  first_read_sensors();//pouze první ctení z cidel
}
 
// The loop function is called in an endless loop
void loop()
{///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//RTC-cteni
	byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
	// retrieve data from DS3231
	readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
//Dallsas - cteni
	if(mov%10==0)
	{
		read_sensors();//cteni z čidel
	}
//DALLAS1_max-min_LCD
	if(teplota1>teplota1M)//Maximalni teplota
		teplota1M=teplota1;
	if(teplota1<teplota1m && teplota1 > float(-120))//minimální teplota
		teplota1m=teplota1;
	lcd.setCursor(0, 0);
	lcd.print("i:" + String(teplota1)+ " ");//vypis vnitrni teploty
//DALLAS0_max-min_LCD
	if(teplota0>teplota0M)//Maximalni teplota
		teplota0M=teplota0;
	if(teplota0<teplota0m && teplota0 > float(-120))//minimální teplota
		teplota0m=teplota0;
	lcd.setCursor(9, 0);//vypis vnejsi teploty
		lcd.print("o:" + String(teplota0) + " ");
//Zobrazeni datumu a min/max hodnot
	lcd.setCursor(7 ,1);//cursor pro pohybujíci se text
	teploty=(" " + String(dayOfMonth) + "." + String(month) + "." + String(year) + "  iM:" + String(teplota1M) + "  im:" + String(teplota1m) + "  oM:" + String(teplota0M) + "  om:" + String(teplota0m) + "                ");//string beziciho textu
	teploty.toCharArray(LCD_teploty,75);
	//Neblokujici posouvani textu na displeji
	unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
	    previousMillis = currentMillis;
	    strncpy(LCD_Tout, &LCD_teploty[mov], 16);//vykopirovani z dlouhyho stringu na zobrazeni na displey
	    mov = mov+10;
	    if(mov>52){
	    	mov=0;
	    }
	}
	lcd.print(LCD_Tout);
//Zobrazeni casu
	lcd.setCursor(0, 1);
	String min0 = String(0);//prida 0 pred jednosnakova cisla
	if (int(minute)<10)
		min0=("0" + String(minute));
	else
		min0 = String(minute);
	lcd.print(String(hour) + ":" + min0);//vypis casu
//Jas Displeje:
	int inJas = analogRead(A11);
	int outJas = 255 - inJas/4;
	if(outJas < 5)
		outJas = 5;
	analogWrite(ledPin, outJas);
}

Závěr

Projekt vyl realizován do plné funkce, jak je vide například v předchozím videu. Pro realizaci hodin bylo testování několik obvodů jako je DS1302 a DS1307, ale zde dochází k problému s verzemi knihoven. U Použitého RTC obvodu DS3231 tento problém nebyl. Dále by se dala efektivněji napsat funkce, která přepíná na dipleji maximální, minimální hodnoty a datum. Vývojové prostředí eclipse s pluginy Arduino bylo použito pro jeho vyšší přívětivost oproti standardnímu prostředí Arduino IDE.

2015/sam3x-clock.txt · Poslední úprava: 2015/12/03 15:20 autor: Marek Stavěl