Platformio code
This commit is contained in:
parent
c685867d51
commit
ede85c0d8e
|
|
@ -0,0 +1,5 @@
|
|||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into executable file.
|
||||
|
||||
The source code of each library should be placed in a an own separate directory
|
||||
("lib/your_library_name/[here are source files]").
|
||||
|
||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
and a contents of `src/main.c`:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
; attiny85 programmed via Arduino Uno, fuses and speed set to 8Mhz:
|
||||
[env:attiny85]
|
||||
platform = atmelavr
|
||||
board = attiny85
|
||||
framework = arduino
|
||||
; Arduino Uno as ISP: (arduino / custom also seen):
|
||||
upload_protocol = stk500v1
|
||||
; each flag in a new line
|
||||
upload_flags =
|
||||
-P$UPLOAD_PORT
|
||||
-b$UPLOAD_SPEED
|
||||
; edit these lines
|
||||
upload_port = /dev/ttyACM0
|
||||
upload_speed = 19200
|
||||
lib_deps = mikem/RadioHead@^1.113
|
||||
; http://eleccelerator.com/fusecalc/fusecalc.php?chip=attiny85
|
||||
board_build.f_cpu = 8000000L
|
||||
; Platformio Project Tasks -> Set Fuses!
|
||||
board_fuses.lfuse = 0xE2
|
||||
board_fuses.hfuse = 0xDF
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
/* Fast DHT Lirary
|
||||
*
|
||||
* Copyright (C) 2015 Sergey Denisov.
|
||||
* Written by Sergey Denisov aka LittleBuster (DenisovS21@gmail.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public Licence
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the Licence, or (at your option) any later version.
|
||||
*
|
||||
* Original library written by Adafruit Industries. MIT license.
|
||||
*
|
||||
* https://github.com/LittleBuster/avr-dht22
|
||||
*/
|
||||
|
||||
#include "dht22.h"
|
||||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
|
||||
#define DHT_COUNT 6
|
||||
#define DHT_MAXTIMINGS 85
|
||||
|
||||
|
||||
void dht_init(struct dht22 *dht, uint8_t pin)
|
||||
{
|
||||
dht->pin = pin;
|
||||
/* Setup the pins! */
|
||||
DDR_DHT &= ~(1 << dht->pin);
|
||||
PORT_DHT |= (1 << dht->pin);
|
||||
}
|
||||
|
||||
static uint8_t dht_read(struct dht22 *dht)
|
||||
{
|
||||
uint8_t tmp;
|
||||
uint8_t sum = 0;
|
||||
uint8_t j = 0, i;
|
||||
uint8_t last_state = 1;
|
||||
uint16_t counter = 0;
|
||||
/*
|
||||
* Pull the pin 1 and wait 250 milliseconds
|
||||
*/
|
||||
PORT_DHT |= (1 << dht->pin);
|
||||
_delay_ms(250);
|
||||
|
||||
dht->data[0] = dht->data[1] = dht->data[2] = dht->data[3] = dht->data[4] = 0;
|
||||
|
||||
/* Now pull it low for ~20 milliseconds */
|
||||
DDR_DHT |= (1 << dht->pin);
|
||||
PORT_DHT &= ~(1 << dht->pin);
|
||||
_delay_ms(20);
|
||||
cli();
|
||||
PORT_DHT |= (1 << dht->pin);
|
||||
_delay_us(40);
|
||||
DDR_DHT &= ~(1 << dht->pin);
|
||||
|
||||
/* Read the timings */
|
||||
for (i = 0; i < DHT_MAXTIMINGS; i++) {
|
||||
counter = 0;
|
||||
while (1) {
|
||||
tmp = ((PIN_DHT & (1 << dht->pin)) >> 1);
|
||||
_delay_us(3);
|
||||
|
||||
if (tmp != last_state)
|
||||
break;
|
||||
|
||||
counter++;
|
||||
_delay_us(1);
|
||||
|
||||
if (counter == 255)
|
||||
break;
|
||||
}
|
||||
|
||||
last_state = ((PIN_DHT & (1 << dht->pin)) >> 1);
|
||||
|
||||
if (counter == 255)
|
||||
break;
|
||||
|
||||
/* Ignore first 3 transitions */
|
||||
if ((i >= 4) && (i % 2 == 0)) {
|
||||
/* Shove each bit into the storage bytes */
|
||||
dht->data[j/8] <<= 1;
|
||||
if (counter > DHT_COUNT)
|
||||
dht->data[j/8] |= 1;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
sei();
|
||||
sum = dht->data[0] + dht->data[1] + dht->data[2] + dht->data[3];
|
||||
|
||||
if ((j >= 40) && (dht->data[4] == (sum & 0xFF)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t dht_read_temp(struct dht22 *dht, float *temp)
|
||||
{
|
||||
if (dht_read(dht)) {
|
||||
*temp = dht->data[2] & 0x7F;
|
||||
*temp *= 256;
|
||||
*temp += dht->data[3];
|
||||
*temp /= 10;
|
||||
|
||||
if (dht->data[2] & 0x80)
|
||||
*temp *= -1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t dht_read_hum(struct dht22 *dht, float *hum)
|
||||
{
|
||||
if (dht_read(dht)) {
|
||||
*hum = dht->data[0];
|
||||
*hum *= 256;
|
||||
*hum += dht->data[1];
|
||||
*hum /= 10;
|
||||
if (*hum == 0.0f)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t dht_read_data(struct dht22 *dht, float *temp, float *hum)
|
||||
{
|
||||
if (dht_read(dht)) {
|
||||
/* Reading temperature */
|
||||
*temp = dht->data[2] & 0x7F;
|
||||
*temp *= 256;
|
||||
*temp += dht->data[3];
|
||||
*temp /= 10;
|
||||
|
||||
if (dht->data[2] & 0x80)
|
||||
*temp *= -1;
|
||||
|
||||
/* Reading humidity */
|
||||
*hum = dht->data[0];
|
||||
*hum *= 256;
|
||||
*hum += dht->data[1];
|
||||
*hum /= 10;
|
||||
if (*hum == 0.0f)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/* struct dht22 AVR Lirary
|
||||
*
|
||||
* Copyright (C) 2015 Sergey Denisov.
|
||||
* Written by Sergey Denisov aka LittleBuster (DenisovS21@gmail.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public Licence
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the Licence, or (at your option) any later version.
|
||||
*
|
||||
* Original library written by Adafruit Industries. MIT license.
|
||||
*
|
||||
* https://github.com/LittleBuster/avr-dht22
|
||||
*/
|
||||
|
||||
#ifndef __DHT22_H__
|
||||
#define __DHT22_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Sensor's port
|
||||
*/
|
||||
#define DDR_DHT DDRB
|
||||
#define PORT_DHT PORTB
|
||||
#define PIN_DHT PINB
|
||||
|
||||
|
||||
struct dht22 {
|
||||
uint8_t data[6]; /* data from sensor store here */
|
||||
uint8_t pin; /* DDR & PORT pin */
|
||||
};
|
||||
|
||||
/**
|
||||
* Init dht sensor
|
||||
* @dht: sensor struct
|
||||
* @pin: PORT & DDR pin
|
||||
*/
|
||||
void dht_init(struct dht22 *dht, uint8_t pin);
|
||||
|
||||
/**
|
||||
* Reading temperature from sensor
|
||||
* @dht: sensor struct
|
||||
* @temp: out temperature pointer
|
||||
*
|
||||
* Returns 1 if succeful reading
|
||||
* Returns 0 if fail reading
|
||||
*/
|
||||
uint8_t dht_read_temp(struct dht22 *dht, float *temp);
|
||||
|
||||
/**
|
||||
* Reading humidity from sensor
|
||||
* @dht: sensor struct
|
||||
* @hum: out humidity pointer
|
||||
*
|
||||
* Returns 1 if succeful reading
|
||||
* Returns 0 if fail reading
|
||||
*/
|
||||
uint8_t dht_read_hum(struct dht22 *dht, float *hum);
|
||||
|
||||
/**
|
||||
* Reading temperature and humidity from sensor
|
||||
* @dht: sensor struct
|
||||
* @temp: out temperature pointer
|
||||
* @hum: out humidity pointer
|
||||
*
|
||||
* Returns 1 if succeful reading
|
||||
* Returns 0 if fail reading
|
||||
*
|
||||
* The fastest function for getting temperature + humidity.
|
||||
*/
|
||||
uint8_t dht_read_data(struct dht22 *dht, float *temp, float *hum);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
RadioHead attiny85 DHT22 Weather Station
|
||||
|
||||
2021 Stefan Ostermann based on several source from the internetz.
|
||||
|
||||
*NOT working in platformio right now!*
|
||||
|
||||
Sources:
|
||||
https://git.cryhost.de/crycode/attiny85-radiohead-dht22-weather-sensor/-/tree/master
|
||||
*/
|
||||
|
||||
|
||||
// pin with the LED connected
|
||||
#define LED_PIN 4
|
||||
|
||||
// blink time for the LED
|
||||
#define LED_TIME 200
|
||||
|
||||
// pin of the DHT22 sensor
|
||||
#define DHT_PIN 1
|
||||
|
||||
// the own RadioHead address
|
||||
#define RH_OWN_ADDR 0xca // 202
|
||||
|
||||
// the server RadioHead address
|
||||
#define RH_SERVER_ADDR 0x01
|
||||
|
||||
// RadioHead bitrate in bit/s
|
||||
#define RH_SPEED 1000
|
||||
|
||||
// pins for the radio hardware
|
||||
#define RH_RX_PIN 5 // not used, set to a non-existent pin
|
||||
#define RH_TX_PIN 3
|
||||
#define RH_PTT_PIN 5 // not used, set to a non-existent pin
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <avr/sleep.h>
|
||||
#include <avr/wdt.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
// for watchdog wakeup
|
||||
// https://gist.github.com/dwhacks/8055287
|
||||
#ifndef cbi
|
||||
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
|
||||
#endif
|
||||
#ifndef sbi
|
||||
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
|
||||
#endif
|
||||
|
||||
|
||||
// DHT22 lib
|
||||
// not using the current adafruit dht library, because it's too memory intensive
|
||||
#include "dht22.h"
|
||||
dht22 dht;
|
||||
|
||||
#define RH_BUF_LEN 5
|
||||
uint8_t rh_buf[RH_BUF_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
// reduce the RadioHead max message length to save memory
|
||||
#define RH_ASK_MAX_MESSAGE_LEN RH_BUF_LEN
|
||||
|
||||
// RadioHead
|
||||
#include <RH_ASK.h>
|
||||
|
||||
|
||||
// Message Headers:
|
||||
#define MSG_START 0x00
|
||||
#define MSG_TEMP 0x01
|
||||
#define MSG_HUMID 0x02
|
||||
#define MSG_BAT 0x03
|
||||
#define MSG_ERR 0xee
|
||||
|
||||
|
||||
RH_ASK rh_driver(RH_SPEED, RH_RX_PIN, RH_TX_PIN, RH_PTT_PIN);
|
||||
|
||||
// watchdog flag
|
||||
volatile boolean f_wdt = 1;
|
||||
|
||||
// temp / humid toggle
|
||||
volatile uint8_t counter = 0;
|
||||
|
||||
|
||||
// prototypes:
|
||||
void gotoSleep(void);
|
||||
|
||||
int getVcc();
|
||||
|
||||
void rh_send(uint8_t len);
|
||||
|
||||
void setup_watchdog(int ii);
|
||||
|
||||
void system_sleep();
|
||||
|
||||
void setup() {
|
||||
// setup the LED pin
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
|
||||
// init the DHT22
|
||||
dht_init(&dht, DHT_PIN);
|
||||
|
||||
|
||||
uint8_t num_blink = 3;
|
||||
|
||||
if (!rh_driver.init()) {
|
||||
num_blink = 5;
|
||||
}
|
||||
|
||||
// blink 3 times
|
||||
for (uint8_t i = 0; i < num_blink; i++) {
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
_delay_ms(LED_TIME);
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
_delay_ms(LED_TIME);
|
||||
}
|
||||
|
||||
// send start message
|
||||
rh_buf[0] = MSG_START;
|
||||
rh_send(1);
|
||||
|
||||
setup_watchdog(6); // approximately 4 seconds sleep
|
||||
|
||||
}
|
||||
|
||||
// main loop
|
||||
void loop() {
|
||||
|
||||
if (f_wdt) {
|
||||
f_wdt = 0;
|
||||
// turn on the LED
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
|
||||
// temperature and humidity
|
||||
float t = 0;//float is 32bit = 1byte
|
||||
float h = 0;
|
||||
long battery = 0;
|
||||
|
||||
if (counter % 4 == 0) {
|
||||
rh_buf[0] = MSG_BAT;
|
||||
battery = getVcc();
|
||||
memcpy(&rh_buf[1], &battery, 4);
|
||||
rh_send(RH_BUF_LEN);
|
||||
}else if (dht_read_data(&dht, &t, &h) == 1) {
|
||||
if (counter % 2 == 0) {
|
||||
rh_buf[0] = MSG_TEMP;
|
||||
memcpy(&rh_buf[1], &t, 4);
|
||||
} else if (counter % 2 == 1) {
|
||||
rh_buf[0] = MSG_HUMID;
|
||||
memcpy(&rh_buf[1], &h, 4);
|
||||
}
|
||||
rh_send(RH_BUF_LEN);
|
||||
} else {
|
||||
// error message
|
||||
rh_buf[0] = MSG_ERR;
|
||||
rh_send(1);
|
||||
|
||||
}
|
||||
counter++;
|
||||
|
||||
// turn off the LED
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
system_sleep();
|
||||
//_delay_ms(1000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// function to send RadioHead messages from the buffer
|
||||
void rh_send(uint8_t len) {
|
||||
rh_driver.send((uint8_t *)rh_buf, len);
|
||||
rh_driver.waitPacketSent();
|
||||
}
|
||||
|
||||
|
||||
|
||||
ISR(WDT_vect)
|
||||
{
|
||||
f_wdt = 1; // set global flag
|
||||
}
|
||||
|
||||
/* set system into the sleep state
|
||||
system wakes up when watchdog is timed out
|
||||
*/
|
||||
void system_sleep() {
|
||||
//cbi(ADCSRA, ADEN); // switch Analog to Digitalconverter OFF
|
||||
|
||||
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
|
||||
sleep_enable();
|
||||
|
||||
sleep_mode(); // System sleeps here
|
||||
|
||||
sleep_disable(); // System continues execution here when watchdog timed out
|
||||
//sbi(ADCSRA, ADEN); // switch Analog to Digitalconverter ON
|
||||
}
|
||||
|
||||
/* 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
|
||||
6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
|
||||
*/
|
||||
void setup_watchdog(int ii) {
|
||||
|
||||
byte bb;
|
||||
int ww;
|
||||
if (ii > 9 ) ii = 9;
|
||||
bb = ii & 7;
|
||||
if (ii > 7) bb |= (1 << 5);
|
||||
bb |= (1 << WDCE);
|
||||
ww = bb;
|
||||
|
||||
MCUSR &= ~(1 << WDRF);
|
||||
// start timed sequence
|
||||
WDTCR |= (1 << WDCE) | (1 << WDE);
|
||||
// set new watchdog timeout value
|
||||
WDTCR = bb;
|
||||
WDTCR |= _BV(WDIE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
From https://github.com/cano64/ArduinoSystemStatus/blob/master/SystemStatus.cpp
|
||||
*/
|
||||
int getVcc() {
|
||||
//reads internal 1V1 reference against VCC
|
||||
ADMUX = _BV(MUX3) | _BV(MUX2); // For ATtiny85/45
|
||||
|
||||
_delay_ms(5);; // Wait for Vref to settle
|
||||
ADCSRA |= _BV(ADSC); // Convert
|
||||
while (bit_is_set(ADCSRA, ADSC));
|
||||
uint8_t low = ADCL;
|
||||
unsigned int val = (ADCH << 8) | low;
|
||||
//discard previous result
|
||||
ADCSRA |= _BV(ADSC); // Convert
|
||||
while (bit_is_set(ADCSRA, ADSC));
|
||||
low = ADCL;
|
||||
val = (ADCH << 8) | low;
|
||||
|
||||
return (long)val;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
This directory is intended for PlatformIO Unit Testing and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PlatformIO Unit Testing:
|
||||
- https://docs.platformio.org/page/plus/unit-testing.html
|
||||
Loading…
Reference in New Issue