Initial
This commit is contained in:
commit
4bc1679242
10 changed files with 454 additions and 0 deletions
51
74C922.c
Normal file
51
74C922.c
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#include "config.h"
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
// Pin Definitions
|
||||||
|
#define ENCODER_A_PIN PD6
|
||||||
|
#define ENCODER_B_PIN PD5
|
||||||
|
#define ENCODER_C_PIN PD4
|
||||||
|
#define ENCODER_D_PIN PD3
|
||||||
|
#define ENCODER_OE_PIN PD2
|
||||||
|
#define ENCODER_DA_PIN PD1
|
||||||
|
|
||||||
|
void prepare_interrupt() {
|
||||||
|
EICRA |= (1 << ISC00); // Any logical change triggers interrupt
|
||||||
|
EIMSK |= (1 << INT0); // INT0 external interrupt
|
||||||
|
PCICR |= (1 << PCIE0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encoder Module
|
||||||
|
void encoder_init() {
|
||||||
|
// Set A, B, C, D, and DA pins as inputs
|
||||||
|
DDRD &= ~((1 << ENCODER_A_PIN) | (1 << ENCODER_B_PIN) | (1 << ENCODER_C_PIN) | (1 << ENCODER_D_PIN) | (1 << ENCODER_DA_PIN));
|
||||||
|
|
||||||
|
// Set OE as output
|
||||||
|
DDRD |= (1 << ENCODER_OE_PIN);
|
||||||
|
|
||||||
|
// Enable internal pull-up resistors for A, B, C, D, and OE pins
|
||||||
|
PORTD |= (1 << ENCODER_A_PIN) | (1 << ENCODER_B_PIN) | (1 << ENCODER_C_PIN) | (1 << ENCODER_D_PIN) | (1 << ENCODER_DA_PIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t encoder_read() {
|
||||||
|
uint8_t encoder_data = 0;
|
||||||
|
|
||||||
|
// Set OE (Output Enable) pin low to enable the encoder
|
||||||
|
PORTD &= ~(1 << ENCODER_OE_PIN);
|
||||||
|
_delay_us(1);
|
||||||
|
|
||||||
|
// Read the state of the encoder
|
||||||
|
encoder_data = PIND >> (ENCODER_A_PIN - 3);
|
||||||
|
encoder_data &= 0x0F;
|
||||||
|
|
||||||
|
// Set OE pin high to disable the encoder
|
||||||
|
PORTD |= (1 << ENCODER_OE_PIN);
|
||||||
|
|
||||||
|
return encoder_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool encoder_available() {
|
||||||
|
return (PIND & (1 << ENCODER_DA_PIN));
|
||||||
|
}
|
8
74C922.h
Normal file
8
74C922.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef H74C922_H
|
||||||
|
#define H74C922_H
|
||||||
|
|
||||||
|
void encoder_init();
|
||||||
|
uint8_t encoder_read();
|
||||||
|
bool encoder_available();
|
||||||
|
|
||||||
|
#endif // 74C922_H
|
78
DHT22.c
Normal file
78
DHT22.c
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "GDM1602K.h"
|
||||||
|
|
||||||
|
#define DATAPIN PC0
|
||||||
|
#define PORT PORTC
|
||||||
|
#define PIN PINC
|
||||||
|
#define DDR DDRC
|
||||||
|
|
||||||
|
bool is_high() {
|
||||||
|
return (PIN & (1 << DATAPIN));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to read data from the DHT22 sensor
|
||||||
|
int DHT22_Read(int *temperature, int *humidity)
|
||||||
|
{
|
||||||
|
// Set the data pin as output
|
||||||
|
DDR |= (1 << DATAPIN);
|
||||||
|
PORT |= (1 << DATAPIN); // Set the pin high, if not already pulled up
|
||||||
|
|
||||||
|
_delay_ms(100);
|
||||||
|
|
||||||
|
// Send start signal
|
||||||
|
PORT &= ~(1 << DATAPIN); // Set the pin low
|
||||||
|
_delay_us(500); // Hold it for a while
|
||||||
|
PORT |= (1 << DATAPIN); // Set the pin high
|
||||||
|
DDR &= ~(1 << DATAPIN); // Data direction in
|
||||||
|
|
||||||
|
_delay_us(20); // Wait for 40 microseconds
|
||||||
|
|
||||||
|
// Sensor should have pulled low here
|
||||||
|
if(PIN & (1 << DATAPIN)) return -2;
|
||||||
|
|
||||||
|
_delay_us(80); // Wait for 80 microseconds
|
||||||
|
|
||||||
|
// Sensor should have pulled high here
|
||||||
|
if(!(PIN & (1 << DATAPIN))) return -1;
|
||||||
|
|
||||||
|
// Read data from the sensor
|
||||||
|
uint8_t data[5] = {0, 0, 0, 0, 0};
|
||||||
|
uint8_t bitMask = 0x80; // All zeroes with MSB high
|
||||||
|
uint8_t byteIndex = 0;
|
||||||
|
|
||||||
|
for (byteIndex = 0; byteIndex < 5; byteIndex++)
|
||||||
|
{
|
||||||
|
for (bitMask = 0x80; bitMask != 0; bitMask >>= 1)
|
||||||
|
{
|
||||||
|
// Wait for the data bit to go low
|
||||||
|
while (!(PIN & (1 << PC0)))
|
||||||
|
;
|
||||||
|
|
||||||
|
// Wait for the data bit to go high
|
||||||
|
_delay_us(20);
|
||||||
|
if (PIN & (1 << PC0))
|
||||||
|
data[byteIndex] |= bitMask;
|
||||||
|
|
||||||
|
// Wait for the data bit to go low (end of bit)
|
||||||
|
while (PIN & (1 << PC0))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify checksum
|
||||||
|
uint8_t checksum = data[0] + data[1] + data[2] + data[3];
|
||||||
|
if (checksum != data[4])
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// Extract temperature and humidity
|
||||||
|
*humidity = ((data[0] << 8) | data[1]);
|
||||||
|
*temperature = ((data[2] << 8) | data[3]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
7
DHT22.h
Normal file
7
DHT22.h
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef DHT22_H
|
||||||
|
#define DHT22_H
|
||||||
|
|
||||||
|
int DHT22_Read(int *temperature, int *humidity);
|
||||||
|
void DHT22_Init();
|
||||||
|
|
||||||
|
#endif /* DHT22_H */
|
141
GDM1602K.c
Normal file
141
GDM1602K.c
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define LCD_DATA_PORT PORTB
|
||||||
|
#define LCD_DATA_DDR DDRB
|
||||||
|
#define LCD_RS_PIN PB1
|
||||||
|
#define LCD_EN_PIN PB2
|
||||||
|
#define LCD_DB4 PB3
|
||||||
|
#define LCD_DB5 PB4
|
||||||
|
#define LCD_DB6 PB5
|
||||||
|
#define LCD_DB7 PB6
|
||||||
|
|
||||||
|
// Delay constants from the datasheet. These are mostly in nanoseconds
|
||||||
|
#define LAG 10
|
||||||
|
#define TW 300
|
||||||
|
#define TSU1 100
|
||||||
|
|
||||||
|
void lcd_4bit_init() {
|
||||||
|
LCD_DATA_DDR = 0xFF;
|
||||||
|
LCD_DATA_PORT = (1 << LCD_DB5);
|
||||||
|
LCD_DATA_PORT &= ~(1 << LCD_RS_PIN);
|
||||||
|
_delay_us(1);
|
||||||
|
LCD_DATA_PORT |= (1 << LCD_EN_PIN);
|
||||||
|
_delay_us(1);
|
||||||
|
LCD_DATA_PORT &= ~(1 << LCD_EN_PIN);
|
||||||
|
_delay_us(1);
|
||||||
|
LCD_DATA_PORT &= ~(1 << LCD_DB5);
|
||||||
|
_delay_us(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_send(bool rs, uint8_t data) {
|
||||||
|
LCD_DATA_DDR = 0xFF;
|
||||||
|
LCD_DATA_PORT = 0x00;
|
||||||
|
|
||||||
|
LCD_DATA_PORT |= (data >> 4) << 3;
|
||||||
|
_delay_us(1);
|
||||||
|
|
||||||
|
// If rs (actual text data), set RS pin high
|
||||||
|
if(rs == true) LCD_DATA_PORT |= (1 << LCD_RS_PIN);
|
||||||
|
|
||||||
|
// Pulse enable
|
||||||
|
_delay_ms(2);
|
||||||
|
LCD_DATA_PORT |= (1 << LCD_EN_PIN);
|
||||||
|
|
||||||
|
_delay_us(1);
|
||||||
|
LCD_DATA_PORT &= ~(1 << LCD_EN_PIN);
|
||||||
|
|
||||||
|
//_delay_us(1);
|
||||||
|
|
||||||
|
// Clear data pins
|
||||||
|
LCD_DATA_PORT &= ~(0x0F << 3);
|
||||||
|
|
||||||
|
// Mask the lower bits and shift accordingly
|
||||||
|
LCD_DATA_PORT |= (data & 0x0F) << 3;
|
||||||
|
_delay_us(1);
|
||||||
|
|
||||||
|
// Pulse enable
|
||||||
|
LCD_DATA_PORT |= (1 << LCD_EN_PIN);
|
||||||
|
_delay_us(1);
|
||||||
|
LCD_DATA_PORT &= ~(1 << LCD_EN_PIN);
|
||||||
|
_delay_us(1);
|
||||||
|
LCD_DATA_PORT &= ~(0x0F << 3);
|
||||||
|
|
||||||
|
LCD_DATA_PORT &= ~(1 << LCD_RS_PIN); // RS Low
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_init() {
|
||||||
|
_delay_ms(100);
|
||||||
|
lcd_4bit_init();
|
||||||
|
|
||||||
|
//lcd_send(1, 0b01111000);
|
||||||
|
lcd_send(0, 0x01); // Clear screen
|
||||||
|
lcd_send(0, 0x02); // Return home
|
||||||
|
lcd_send(0, 0b00001100); // Display on, no cursor
|
||||||
|
lcd_send(0, 0b00101000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_clear() {
|
||||||
|
lcd_send(0, 0x01);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_leds() {
|
||||||
|
DDRB |= 0xFF;
|
||||||
|
PORTB = (1 << LCD_DB4);
|
||||||
|
_delay_us(1);
|
||||||
|
PORTB = (1 << LCD_DB5);
|
||||||
|
_delay_us(1);
|
||||||
|
PORTB = (1 << LCD_DB6);
|
||||||
|
_delay_us(1);
|
||||||
|
PORTB = (1 << LCD_DB7);
|
||||||
|
_delay_us(1);
|
||||||
|
|
||||||
|
PORTB = (1 << LCD_EN_PIN);
|
||||||
|
_delay_us(1);
|
||||||
|
PORTB = (1 << LCD_RS_PIN);
|
||||||
|
_delay_us(1);
|
||||||
|
PORTB = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_set_cursor(uint8_t row, uint8_t col) {
|
||||||
|
uint8_t position = 0x80;
|
||||||
|
|
||||||
|
if (row == 1) position += 0x40;
|
||||||
|
|
||||||
|
position += col;
|
||||||
|
lcd_send(0, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes a string and splits it over two lines if needed. Max length is 32 characters.
|
||||||
|
void lcd_write_string(const char* string) {
|
||||||
|
uint8_t i = 0;
|
||||||
|
while(string[i]) {
|
||||||
|
if(i == 16) {
|
||||||
|
lcd_set_cursor(1, 0);
|
||||||
|
while(string[i] == ' ') i++; // Skip leading spaces on the new line
|
||||||
|
}
|
||||||
|
lcd_send(1, string[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes two separate strings and prints them on their corresponding row
|
||||||
|
void lcd_write_strings(const char* top, const char* bottom) {
|
||||||
|
uint8_t i = 0;
|
||||||
|
|
||||||
|
while (top[i]) {
|
||||||
|
lcd_send(1, top[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
lcd_set_cursor(1, 0);
|
||||||
|
while(bottom[i]) {
|
||||||
|
lcd_send(1, bottom[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
9
GDM1602K.h
Normal file
9
GDM1602K.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef GDM1602K_H_
|
||||||
|
#define GDM1602K_H_
|
||||||
|
|
||||||
|
void lcd_write_strings(const char* top, const char* bottom);
|
||||||
|
void lcd_write_string(const char* string);
|
||||||
|
void lcd_init();
|
||||||
|
void lcd_clear();
|
||||||
|
|
||||||
|
#endif /* GDM1602K_H_ */
|
47
LM335.c
Normal file
47
LM335.c
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#include "config.h"
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include "LM335.h"
|
||||||
|
|
||||||
|
void ADC_Init()
|
||||||
|
{
|
||||||
|
// Set AVCC as the voltage reference with external capacitor at AREF pin
|
||||||
|
ADMUX = (1 << REFS0);
|
||||||
|
|
||||||
|
// Set ADC clock prescaler to 64 (125kHz ADC clock)
|
||||||
|
ADCSRA = (1 << ADPS2) | (1 << ADPS1);
|
||||||
|
|
||||||
|
// Enable ADC, enable interrupts
|
||||||
|
ADCSRA |= (1 << ADEN); // | (1 << ADIE);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ADC_Read(uint8_t channel)
|
||||||
|
{
|
||||||
|
// Select ADC channel
|
||||||
|
ADMUX = (ADMUX & 0xF8) | (channel & 0x07);
|
||||||
|
|
||||||
|
// Start ADC conversion
|
||||||
|
ADCSRA |= (1 << ADSC);
|
||||||
|
|
||||||
|
// Wait for ADC conversion to complete
|
||||||
|
while (ADCSRA & (1 << ADSC))
|
||||||
|
;
|
||||||
|
|
||||||
|
// Read ADC result
|
||||||
|
return ADC;
|
||||||
|
}
|
||||||
|
|
||||||
|
float LM335_ReadTemperature()
|
||||||
|
{
|
||||||
|
// Read ADC value from LM335 pin (PA0)
|
||||||
|
uint16_t adcValue = ADC_Read(0x00);
|
||||||
|
|
||||||
|
float vref = 4.64;
|
||||||
|
int vfactor = 100;
|
||||||
|
float voltage = (adcValue * vref) / 1024;
|
||||||
|
|
||||||
|
// Calculate temperature in Celsius using LM335 formula
|
||||||
|
float temperature = (voltage - 2.92) * vfactor;
|
||||||
|
|
||||||
|
return temperature;
|
||||||
|
}
|
13
LM335.h
Normal file
13
LM335.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
|
||||||
|
#ifndef LM335_H_
|
||||||
|
#define LM335_H_
|
||||||
|
|
||||||
|
#define LM335_PIN PA0
|
||||||
|
|
||||||
|
void ADC_Init();
|
||||||
|
uint16_t ADC_Read(uint8_t channel);
|
||||||
|
float LM335_ReadTemperature();
|
||||||
|
|
||||||
|
#endif
|
6
config.h
Normal file
6
config.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef CONFIG_H
|
||||||
|
#define CONFIG_H
|
||||||
|
|
||||||
|
#define F_CPU 1600000UL
|
||||||
|
|
||||||
|
#endif // CONFIG_H
|
94
main.c
Normal file
94
main.c
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "74C922.h"
|
||||||
|
#include "DHT22.h"
|
||||||
|
#include "GDM1602K.h"
|
||||||
|
#include "LM335.h"
|
||||||
|
|
||||||
|
enum DisplayMode {TEMP, AVG};
|
||||||
|
|
||||||
|
bool b = false;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
_delay_ms(1000); // Boot up time, let components catch up
|
||||||
|
lcd_init();
|
||||||
|
encoder_init();
|
||||||
|
|
||||||
|
lcd_clear();
|
||||||
|
lcd_write_string("Hello, world!");
|
||||||
|
|
||||||
|
int temp, hum;
|
||||||
|
char celc_str[30];
|
||||||
|
char temp_with_unit[20] = "";
|
||||||
|
char hum_str[30];
|
||||||
|
float celcius = 0.0;
|
||||||
|
float humidity = 0.0;
|
||||||
|
char temp_unit = 'C';
|
||||||
|
|
||||||
|
uint8_t button_data;
|
||||||
|
char btn_string[30];
|
||||||
|
bool btn_just_pressed = false;
|
||||||
|
|
||||||
|
long loops = 0;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
// If encoder has data available
|
||||||
|
if(encoder_available() == true) {
|
||||||
|
loops = 0xFFFF;
|
||||||
|
if(!btn_just_pressed) {
|
||||||
|
btn_just_pressed = true;
|
||||||
|
button_data = encoder_read();
|
||||||
|
sprintf(btn_string, "Knapp %d", button_data);
|
||||||
|
lcd_clear();
|
||||||
|
if(button_data == 11) {
|
||||||
|
if(temp_unit == 'C') temp_unit = 'F';
|
||||||
|
else if(temp_unit == 'F') temp_unit = 'K';
|
||||||
|
else if(temp_unit == 'K') temp_unit = 'C';
|
||||||
|
loops = 0;
|
||||||
|
}
|
||||||
|
if(button_data == 3) {
|
||||||
|
sprintf(celc_str, "10h Tmp: %s", temp_with_unit);
|
||||||
|
sprintf(hum_str, "10h Hum: %.1f%%", humidity-1);
|
||||||
|
lcd_write_strings(celc_str, hum_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
btn_just_pressed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(loops == 0) {
|
||||||
|
loops = 0x2FFFF;
|
||||||
|
|
||||||
|
int result = DHT22_Read(&temp, &hum);
|
||||||
|
|
||||||
|
lcd_clear();
|
||||||
|
|
||||||
|
if(result == 0) {
|
||||||
|
celcius = ((float)temp)/10.0;
|
||||||
|
humidity = ((float) hum)/10.0;
|
||||||
|
switch(temp_unit) {
|
||||||
|
case 'C':
|
||||||
|
sprintf(temp_with_unit, "%.1f %c", celcius, temp_unit);
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
sprintf(temp_with_unit, "%.1f %c", celcius*9/5+32, temp_unit);
|
||||||
|
break;
|
||||||
|
case 'K':
|
||||||
|
sprintf(temp_with_unit, "%.1f %c", celcius + 273.15, temp_unit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sprintf(celc_str, "Temp: %s", temp_with_unit);
|
||||||
|
sprintf(hum_str, "Humidity: %.1f%%", humidity);
|
||||||
|
|
||||||
|
lcd_write_strings(celc_str, hum_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loops--;
|
||||||
|
}
|
||||||
|
lcd_write_string("Exited...");
|
||||||
|
}
|
Loading…
Reference in a new issue