restructured

This commit is contained in:
Martin Brodbeck 2022-05-31 15:13:00 +02:00
parent 2f7d1dd921
commit 91e1a7d424
12 changed files with 33 additions and 28 deletions

31
src/CMakeLists.txt Normal file
View file

@ -0,0 +1,31 @@
configure_file(config.h.in ${PROJECT_BINARY_DIR}/src/config.h)
set(SOURCES
gbmanager.cpp
lcd.cpp
ds18b20.cpp
relais.cpp
)
# Add executable. Default name is the project name, version 0.1
add_executable(gbmanager ${SOURCES})
pico_set_program_name(gbmanager "gbmanager")
pico_set_program_version(gbmanager ${PROJECT_VERSION})
pico_enable_stdio_uart(gbmanager 1)
pico_enable_stdio_usb(gbmanager 0)
pico_generate_pio_header(gbmanager ${CMAKE_CURRENT_LIST_DIR}/ds18b20.pio)
# Add the standard library to the build
target_link_libraries(gbmanager pico_stdlib)
# Add any user requested libraries
target_link_libraries(gbmanager
hardware_i2c
hardware_gpio
hardware_pio
)
pico_add_extra_outputs(gbmanager)

6
src/config.h.in Normal file
View file

@ -0,0 +1,6 @@
#ifndef CONFIG_H
#define CONFIG_H
#cmakedefine PROJECT_VERSION "@PROJECT_VERSION@"
#endif

72
src/ds18b20.cpp Normal file
View file

@ -0,0 +1,72 @@
#include "ds18b20.h"
DS18B20::DS18B20(PIO pio, uint8_t gpio) : pio{pio}, gpio{gpio} {
uint offset = pio_add_program(pio, &ds18b20_program);
stateMachineIndex = pio_claim_unused_sm(pio, true);
pio_gpio_init(pio, gpio);
pio_sm_config c = ds18b20_program_get_default_config(offset);
sm_config_set_clkdiv_int_frac(&c, 255, 0);
sm_config_set_set_pins(&c, gpio, 1);
sm_config_set_out_pins(&c, gpio, 1);
sm_config_set_in_pins(&c, gpio);
sm_config_set_in_shift(&c, true, true, 8);
pio_sm_init(pio0, stateMachineIndex, offset, &c);
pio_sm_set_enabled(pio0, stateMachineIndex, true);
}
void DS18B20::writeBytes(uint8_t bytes[], int len) {
pio_sm_put_blocking(pio, stateMachineIndex, 250);
pio_sm_put_blocking(pio, stateMachineIndex, len - 1);
for (int i = 0; i < len; i++) {
pio_sm_put_blocking(pio, stateMachineIndex, bytes[i]);
}
}
void DS18B20::readBytes(uint8_t bytes[], int len) {
pio_sm_put_blocking(pio, stateMachineIndex, 0);
pio_sm_put_blocking(pio, stateMachineIndex, len - 1);
for (int i = 0; i < len; i++) {
bytes[i] = pio_sm_get_blocking(pio, stateMachineIndex) >> 24;
}
}
void DS18B20::convert() {
uint8_t d[2] = {0xCC, 0x44};
writeBytes(d, 2);
}
uint8_t DS18B20::crc8(uint8_t *data, uint8_t len) {
uint8_t i;
uint8_t j;
uint8_t temp;
uint8_t databyte;
uint8_t crc = 0;
for (i = 0; i < len; i++) {
databyte = data[i];
for (j = 0; j < 8; j++) {
temp = (crc ^ databyte) & 0x01;
crc >>= 1;
if (temp)
crc ^= 0x8C;
databyte >>= 1;
}
}
return crc;
}
float DS18B20::getTemperature() {
uint8_t d[2] = {0xCC, 0xBE};
writeBytes(d, 2);
uint8_t data[9];
readBytes(data, 9);
uint8_t crc = crc8(data, 9);
if (crc != 0)
return -2000;
int t1 = data[0];
int t2 = data[1];
int16_t temp1 = (t2 << 8 | t1);
volatile float temp = (float)temp1 / 16;
return temp;
}

23
src/ds18b20.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef DS18B20_H
#define DS18B20_H
#include "ds18b20.pio.h"
#include "hardware/gpio.h"
#include "pico/stdlib.h"
class DS18B20 {
public:
DS18B20(PIO pio, uint8_t gpio);
float getTemperature();
void convert();
private:
uint8_t crc8(uint8_t *data, uint8_t len);
void writeBytes(uint8_t bytes[], int len);
void readBytes(uint8_t bytes[], int len);
PIO pio;
uint8_t gpio;
uint stateMachineIndex;
};
#endif

44
src/ds18b20.pio Normal file
View file

@ -0,0 +1,44 @@
.program ds18b20
.wrap_target
again:
pull block
mov x, osr
jmp !x, read
write: set pindirs, 1
set pins, 0
loop1:
jmp x--,loop1
set pindirs, 0 [31]
wait 1 pin 0 [31]
pull block
mov x, osr
bytes1:
pull block
set y, 7
set pindirs, 1
bit1:
set pins, 0 [1]
out pins,1 [31]
set pins, 1 [20]
jmp y--,bit1
jmp x--,bytes1
set pindirs, 0 [31]
jmp again
read:
pull block
mov x, osr
bytes2:
set y, 7
bit2:
set pindirs, 1
set pins, 0 [1]
set pindirs, 0 [5]
in pins,1 [10]
jmp y--,bit2
jmp x--,bytes2
.wrap

80
src/gbmanager.cpp Normal file
View file

@ -0,0 +1,80 @@
#include <iomanip>
#include <iostream>
#include <sstream>
#include "hardware/i2c.h"
#include "pico/stdlib.h"
#include "config.h"
#include "ds18b20.h"
#include "lcd.h"
#include "relais.h"
// GPIOs used
constexpr uint I2C_SDA_PIN = 26;
constexpr uint I2C_SCL_PIN = 27;
constexpr uint DS18B20_PIN = 28;
constexpr uint RELAIS_PIN = 18;
// Custom chars for the LCD
constexpr char CUSTOM_CHAR_DEG = 0xDF;
constexpr char CUSTOM_CHAR_AE = 0xE1;
using std::string;
int main() {
// Enable UART so we can print status output
stdio_init_all();
// Initialize the LCD
auto myLCD = LCD(i2c1, I2C_SDA_PIN, I2C_SCL_PIN);
myLCD.clear();
// Initialize the temp sensor
// DS18B20 ds = DS18B20(pio0, DS18B20_PIN);
// Initialize the relais
Relais relais(RELAIS_PIN);
float temp_act{0};
float temp_tgt{28.0};
float temp_diff{0.5};
std::stringstream lcdText{};
bool isHeating = false;
bool isSystemOn = false;
string heatInfo{" "};
string systemInfo{"OFF"};
lcdText << " G" << CUSTOM_CHAR_AE << "rbox Manager\n (Ver. "
<< PROJECT_VERSION << ")";
myLCD.sendString(lcdText.str());
sleep_ms(3000);
while (true) {
// ds.convert();
sleep_ms(750);
// temp_act = ds.getTemperature();
temp_act = 23.5;
if (isSystemOn && temp_act < temp_tgt - temp_diff) {
isHeating = true;
} else if (isSystemOn && temp_act > temp_tgt + temp_diff) {
isHeating = false;
} else if (!isSystemOn) {
isHeating = false;
}
isHeating ? heatInfo = ">H<" : heatInfo = " ";
relais.activate(isHeating);
lcdText.str("");
lcdText.clear();
lcdText.precision(4);
lcdText << "ACT: " << temp_act << CUSTOM_CHAR_DEG << "C " << heatInfo
<< "\n"
<< "TGT: " << temp_tgt << CUSTOM_CHAR_DEG << "C " << systemInfo;
myLCD.setCursor(0, 0);
myLCD.sendString(lcdText.str());
}
}

98
src/lcd.cpp Normal file
View file

@ -0,0 +1,98 @@
#include "lcd.h"
// commands
constexpr int LCD_CLEARDISPLAY = 0x01;
constexpr int LCD_RETURNHOME = 0x02;
constexpr int LCD_ENTRYMODESET = 0x04;
constexpr int LCD_DISPLAYCONTROL = 0x08;
constexpr int LCD_CURSORSHIFT = 0x10;
constexpr int LCD_FUNCTIONSET = 0x20;
constexpr int LCD_SETCGRAMADDR = 0x40;
constexpr int LCD_SETDDRAMADDR = 0x80;
// flags for display entry mode
constexpr int LCD_ENTRYSHIFTINCREMENT = 0x01;
constexpr int LCD_ENTRYLEFT = 0x02;
// flags for display and cursor control
constexpr int LCD_BLINKON = 0x01;
constexpr int LCD_CURSORON = 0x02;
constexpr int LCD_DISPLAYON = 0x04;
// flags for function set
constexpr int LCD_5x10DOTS = 0x04;
constexpr int LCD_2LINE = 0x08;
constexpr int LCD_8BITMODE = 0x10;
constexpr int LCD_BACKLIGHT = 0x08;
constexpr int LCD_ENABLE_BIT = 0x04;
LCD::LCD(i2c_inst_t *i2c, const uint gpio_sda, const uint gpio_scl,
const uint8_t i2c_addr, uint8_t num_cols, uint8_t num_lines)
: i2c{i2c}, i2c_addr{i2c_addr}, num_cols{num_cols}, num_lines{num_lines} {
i2c_init(i2c1, 100 * 1000);
gpio_set_function(gpio_sda, GPIO_FUNC_I2C);
gpio_set_function(gpio_scl, GPIO_FUNC_I2C);
gpio_pull_up(gpio_sda);
gpio_pull_up(gpio_scl);
sendByte(0x03, Mode::COMMAND);
sendByte(0x03, Mode::COMMAND);
sendByte(0x03, Mode::COMMAND);
sendByte(0x02, Mode::COMMAND);
sendByte(LCD_ENTRYMODESET | LCD_ENTRYLEFT, Mode::COMMAND);
sendByte(LCD_FUNCTIONSET | LCD_2LINE, Mode::COMMAND);
sendByte(LCD_DISPLAYCONTROL | LCD_DISPLAYON, Mode::COMMAND);
clear();
}
// go to location on LCD
void LCD::setCursor(int line, int position) {
int val = (line == 0) ? 0x80 + position : 0xC0 + position;
sendByte(val, Mode::COMMAND);
cursor_x = line;
cursor_y = position;
}
void LCD::sendChar(char val) { sendByte(val, Mode::CHARACTER); }
void LCD::sendString(const std::string &str) {
for (const char &c : str) {
if (c == '\n') {
cursor_y++;
setCursor(cursor_y, 0);
} else {
sendChar(c);
cursor_x++;
}
}
}
void LCD::clear() { sendByte(LCD_CLEARDISPLAY, Mode::COMMAND); }
void LCD::i2cWriteByte(uint8_t val) {
i2c_write_blocking(i2c, i2c_addr, &val, 1, false);
}
void LCD::toggleEnable(uint8_t val) {
// Toggle enable pin on LCD display
// We cannot do this too quickly or things don't work
constexpr uint64_t DELAY_US = 600;
sleep_us(DELAY_US);
i2cWriteByte(val | LCD_ENABLE_BIT);
sleep_us(DELAY_US);
i2cWriteByte(val & ~LCD_ENABLE_BIT);
sleep_us(DELAY_US);
}
// The display is sent a byte as two separate nibble transfers
void LCD::sendByte(uint8_t val, Mode mode) {
uint8_t high = static_cast<int>(mode) | (val & 0xF0) | LCD_BACKLIGHT;
uint8_t low = static_cast<int>(mode) | ((val << 4) & 0xF0) | LCD_BACKLIGHT;
i2cWriteByte(high);
toggleEnable(high);
i2cWriteByte(low);
toggleEnable(low);
}

34
src/lcd.h Normal file
View file

@ -0,0 +1,34 @@
#ifndef LCD_H
#define LCD_H
#include <string>
#include "hardware/i2c.h"
#include "pico/stdlib.h"
enum class Mode { COMMAND, CHARACTER };
class LCD {
public:
LCD(i2c_inst_t *i2c, const uint gpio_sda, const uint gpio_scl,
const uint8_t i2c_addr = 0x27, uint8_t num_cols = 16,
uint8_t num_lines = 2);
void sendString(const std::string &str);
void setCursor(int line, int position);
void clear();
private:
void sendByte(uint8_t val, Mode mode);
void toggleEnable(uint8_t val);
void i2cWriteByte(uint8_t val);
void sendChar(char val);
i2c_inst_t *i2c;
uint8_t i2c_addr;
uint8_t num_cols;
uint8_t num_lines;
uint8_t cursor_x{0};
uint8_t cursor_y{0};
};
#endif

19
src/relais.cpp Normal file
View file

@ -0,0 +1,19 @@
#include "relais.h"
Relais::Relais(uint gpio) : gpio{gpio} {
gpio_set_dir(gpio, true);
gpio_init(gpio);
off();
}
void Relais::activate(bool active) {
if (active) {
gpio_pull_down(gpio);
} else {
gpio_pull_up(gpio);
}
}
void Relais::on() { activate(true); }
void Relais::off() { activate(false); }

18
src/relais.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef RELAIS_H
#define RELAIS_H
#include "hardware/gpio.h"
#include "pico/stdlib.h"
class Relais {
public:
Relais(uint gpio);
void activate(bool active);
void on();
void off();
private:
uint gpio;
};
#endif