ADC support and shared output buffer

pull/16/head
Martin Ger 2017-10-12 21:17:41 +02:00
rodzic ed3a3b621e
commit f89c74a715
15 zmienionych plików z 163 dodań i 32 usunięć

Wyświetl plik

@ -33,7 +33,7 @@ ESPPORT ?= /dev/ttyUSB0
TARGET = app
# which modules (subdirectories) of the project to include in compiling
MODULES = driver user mqtt ntp easygpio pwm httpclient
MODULES = driver user mqtt ntp easygpio pwm httpclient adc
#EXTRA_INCDIR = $(BUILD_AREA)/esp-open-sdk/esp-open-lwip/include include
EXTRA_INCDIR = include

Wyświetl plik

@ -1,7 +1,7 @@
# esp_uMQTT_broker
An MQTT Broker/Client with scripting support on the ESP8266
This program enables the ESP8266 to become the central node in a small distributed IoT system. It implements an MQTT Broker and a simple scripted rule engine with event/action statements that links together the MQTT sensors and actors. It can act as STA, as AP, or as both and it can connect to another MQTT broker (i.e. in the cloud). Here it can act as bridge and forward and rewrite topics in both directions. Also it can parse JSON structures, write to local GPIO pins, react on timers and GPIO interrupts, drive GPIO pins with PWM, and do basic HTTP GET requests.
This program enables the ESP8266 to become the central node in a small distributed IoT system. It implements an MQTT Broker and a simple scripted rule engine with event/action statements that links together the MQTT sensors and actors. It can act as STA, as AP, or as both and it can connect to another MQTT broker (i.e. in the cloud). Here it can act as bridge and forward and rewrite topics in both directions. Also it can parse JSON structures, send basic HTTP GET requests and do basic I/O: i.e. read and write to local GPIO pins, react on timers and GPIO interrupts, drive GPIO pins with PWM, and read the ADC.
Find a video that explains the ideas and the architecture of the project at: https://www.youtube.com/watch?v=0K9q4IuB_oA
@ -227,6 +227,11 @@ If an *MqttAuthCallback* function is registered with MQTT_server_onAuth(), it is
The *MqttConnectCallback* function does a similar check for the connection, but it is called right after the connect request before any internal status is allocated. This is done in order to reject requests from unautorized clients in an early stage.
# Limitations on the number of clients
To adjust memory consumption of one MQTT connection and thus the max number of concurrent connections you can redefine MQTT_BUF_SIZE and QUEUE_BUFFER_SIZE in "user_config.h". MQTT_BUF_SIZE is the max. size of pending inbound messages for one connection (and thus also the max. size of a single MQTT message) and QUEUE_BUFFER_SIZE is the max. size of all pending outbound messages for one connection. Currently these parameters are set to 1024 resp. 2048 bytes, resulting in a memory consumption of about 4 KB per connection and a max number of connections of about 8-9 (depending on the memory usage of the rest of the program). When you reduce buffer sizes, e.g. to 512 and 1024 bytes, a single connection requires only about 2.5 KB resulting in up to 13 possible concurrent MQTT connections. In any case you have to increase the number of TCP connections (default 5) first by calling "espconn_tcp_set_max_con(n)" with n, the max. number of concurrent TCP connections, less or equal to 15.
Also there is a hard limitation on the number of STAs connected to the SoftAP, which is 8. I.e. when using the esp_uMQTT_broker only with clients via the SoftAP interface, even with reduced memory consumtion, the limit of different client nodes is still 8, as it is imposed by the binary WiFi driver. Only when used via the STA interface and an external AP you can connect more than 8 MQTT clients.
# Thanks
- pfalcon for esp_open_sdk (https://github.com/martin-ger/esp-open-sdk)
- tuanpmt for esp_mqtt (https://github.com/tuanpmt/esp_mqtt )

Wyświetl plik

@ -1,4 +1,5 @@
# Scripting Language
Scripting Language
==================
The scripting language of the esp_uMQTT_broker is stricly event based. It mainly consists of "on _event_ do _action_" clauses. An event can be:
- the reception of an MQTT item,
@ -56,7 +57,7 @@ In general, scripts conform to the following BNF:
<op> := '=' | '>' | gte | str_ge | str_gte | '+' | '-' | '*' | '|' | div
<val> := <string> | <const> | #<hex-string> | $[any ASCII]* | @<num> |
gpio_in(<num>) | $this_item | $this_data | $this_gpio |
gpio_in(<num>) | $adc | $this_item | $this_data | $this_gpio |
$this_http_code | $this_http_body | $timestamp | $weekday
<string> := "[any ASCII]*" | [any ASCII]*
@ -223,13 +224,14 @@ gpio_in(<num>)
Reads the current boolean input value of the given GPIO pin. This pin has to be defined as input before using the "gpio_pinmode" action.
```
$this_item | $this_data | $this_gpio | $timestamp | $weekday | $this_http_body | $this_http_code
$adc | $this_item | $this_data | $this_gpio | $timestamp | $weekday | $this_http_body | $this_http_code
```
Special variables:
$this_topic and $this_data are only defined in "on topic" clauses and contain the current topic and its data.
$this_gpio contains the state of the GPIO in an "on gpio_interrupt" clause.
$timestamp contains the current time of day in "hh:mm:ss" format. If no NTP sync happened the time will be reported as "99:99:99". $weekday returns the day of week as three letters ("Mon","Tue",...).
$this_http_body and $this_http_code are only defined inside the "on http_response" clause and contain the body of an HTTP response and the HTTP return code.
- $adc gives you the current value of the ADC (analog to digital input pin)
- $this_topic and $this_data are only defined in "on topic" clauses and contain the current topic and its data.
- $this_gpio contains the state of the GPIO in an "on gpio_interrupt" clause.
- $timestamp contains the current time of day in "hh:mm:ss" format. If no NTP sync happened the time will be reported as "99:99:99". $weekday returns the day of week as three letters ("Mon","Tue",...).
- $this_http_body and $this_http_code are only defined inside the "on http_response" clause and contain the body of an HTTP response and the HTTP return code.
# Operators
Operators are used to combine values and expressions.
@ -242,7 +244,7 @@ These operators result in boolean values and are typically used in comparisons i
```
'+' | '-' | '*' | div
```
These operators are the arithmetical operations. CAUTION: arithmetical preceedence does not (yet) apply automatically, all expressions are evaluated from left to right. I.e. "2+3*4" evaluates to 20 instead of 14. However, the preceedence can be fully controlled by brackets. Write "2+(3*4)" instead.
These operators are the arithmetical operations. CAUTION: arithmetical preceedence does not (yet) apply automatically, all expressions are evaluated from left to right. I.e. "2+3\*4" evaluates to 20 instead of 14. However, the preceedence can be fully controlled by brackets. Write "2+(3\*4)" instead.
```
'|'
@ -376,3 +378,4 @@ do
publish local $command_topic "off"
```

75
adc/adc.c 100644
Wyświetl plik

@ -0,0 +1,75 @@
#include "ets_sys.h"
#include "osapi.h"
#include "adc.h"
#define i2c_bbpll 0x67
#define i2c_bbpll_en_audio_clock_out 4
#define i2c_bbpll_en_audio_clock_out_msb 7
#define i2c_bbpll_en_audio_clock_out_lsb 7
#define i2c_bbpll_hostid 4
#define i2c_saradc 0x6C
#define i2c_saradc_hostid 2
#define i2c_saradc_en_test 0
#define i2c_saradc_en_test_msb 5
#define i2c_saradc_en_test_lsb 5
#define i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata) \
rom_i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata)
#define i2c_readReg_Mask(block, host_id, reg_add, Msb, Lsb) \
rom_i2c_readReg_Mask_(block, host_id, reg_add, Msb, Lsb)
#define i2c_writeReg_Mask_def(block, reg_add, indata) \
i2c_writeReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb, indata)
#define i2c_readReg_Mask_def(block, reg_add) \
i2c_readReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb)
#ifdef ADC_DEBUG
#define ADC_DBG os_printf
#else
#define ADC_DBG
#endif
uint16 ICACHE_FLASH_ATTR adc_read(void)
{
uint8 i;
uint16 sar_dout, tout, sardata[8];
i2c_writeReg_Mask_def(i2c_saradc, i2c_saradc_en_test, 1); //select test mux
//PWDET_CAL_EN=0, PKDET_CAL_EN=0
SET_PERI_REG_MASK(0x60000D5C, 0x200000);
while (GET_PERI_REG_BITS(0x60000D50, 26, 24) > 0); //wait r_state == 0
sar_dout = 0;
CLEAR_PERI_REG_MASK(0x60000D50, 0x02); //force_en=0
SET_PERI_REG_MASK(0x60000D50, 0x02); //force_en=1
os_delay_us(2);
while (GET_PERI_REG_BITS(0x60000D50, 26, 24) > 0); //wait r_state == 0
read_sar_dout(sardata);
for (i = 0; i < 8; i++) {
sar_dout += sardata[i];
ADC_DBG("%d, ", sardata[i]);
}
tout = (sar_dout + 8) >> 4; //tout is 10 bits fraction
i2c_writeReg_Mask_def(i2c_saradc, i2c_saradc_en_test, 1); //select test mux
while (GET_PERI_REG_BITS(0x60000D50, 26, 24) > 0); //wait r_state == 0
CLEAR_PERI_REG_MASK(0x60000D5C, 0x200000);
SET_PERI_REG_MASK(0x60000D60, 0x1); //force_en=1
CLEAR_PERI_REG_MASK(0x60000D60, 0x1); //force_en=1
return tout; //tout is 10 bits fraction
}

6
adc/adc.h 100644
Wyświetl plik

@ -0,0 +1,6 @@
#ifndef __ADC_H__
#define __ADC_H__
uint16 adc_read(void);
#endif

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -1,2 +1,2 @@
8c0436ab218b8b4165f57501775797e09e818ae0 0x00000.bin
b02f819746fe72bb7692e9c6bb2c37d175f58b24 0x10000.bin
25afd95372b46210eedc30515d63589985c2d281 0x00000.bin
3ef293f39d57c0379b8c9ec4795fb38360d2b214 0x10000.bin

Wyświetl plik

@ -278,7 +278,7 @@ void ICACHE_FLASH_ATTR mqtt_tcpclient_recv(void *arg, char *pdata, unsigned shor
struct espconn *pCon = (struct espconn *)arg;
MQTT_Client *client = (MQTT_Client *) pCon->reverse;
client->keepAliveTick = 0;
//client->keepAliveTick = 0;
READPACKET:
MQTT_INFO("TCP: data received %d bytes\r\n", len);
// MQTT_INFO("STATE: %d\r\n", client->connState);
@ -722,6 +722,7 @@ void ICACHE_FLASH_ATTR MQTT_Task(os_event_t * e) {
client->sendTimeout = MQTT_SEND_TIMOUT;
MQTT_INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type,
client->mqtt_state.pending_msg_id);
client->keepAliveTick = 0;
if (client->security) {
#ifdef MQTT_SSL_ENABLE
espconn_secure_send(client->pCon, dataBuffer, dataLen);

Wyświetl plik

@ -22,10 +22,6 @@ return _v;
#define os_malloc(x) my_os_zalloc(x, __LINE__)
*/
#ifndef QUEUE_BUFFER_SIZE
#define QUEUE_BUFFER_SIZE 2048
#endif
#define MAX_SUBS_PER_REQ 16
#define MQTT_SERVER_TASK_PRIO 1
@ -125,6 +121,8 @@ bool ICACHE_FLASH_ATTR activate_next_client() {
return true;
}
static uint8_t shared_out_buffer[MQTT_BUF_SIZE];
bool ICACHE_FLASH_ATTR MQTT_InitClientCon(MQTT_ClientCon * mqttClientCon) {
uint32_t temp;
MQTT_INFO("MQTT:InitClientCon\r\n");
@ -138,7 +136,8 @@ bool ICACHE_FLASH_ATTR MQTT_InitClientCon(MQTT_ClientCon * mqttClientCon) {
mqttClientCon->mqtt_state.in_buffer = (uint8_t *) os_zalloc(MQTT_BUF_SIZE);
mqttClientCon->mqtt_state.in_buffer_length = MQTT_BUF_SIZE;
mqttClientCon->mqtt_state.out_buffer = (uint8_t *) os_zalloc(MQTT_BUF_SIZE);
// mqttClientCon->mqtt_state.out_buffer = (uint8_t *) os_zalloc(MQTT_BUF_SIZE);
mqttClientCon->mqtt_state.out_buffer = shared_out_buffer;
mqttClientCon->mqtt_state.out_buffer_length = MQTT_BUF_SIZE;
mqttClientCon->mqtt_state.connect_info = &mqttClientCon->connect_info;
@ -182,18 +181,20 @@ bool ICACHE_FLASH_ATTR MQTT_DeleteClientCon(MQTT_ClientCon * mqttClientCon) {
mqttClientCon->mqtt_state.in_buffer = NULL;
}
if (mqttClientCon->mqtt_state.out_buffer != NULL) {
os_free(mqttClientCon->mqtt_state.out_buffer);
mqttClientCon->mqtt_state.out_buffer = NULL;
}
/* We use one static buffer for all connections
// if (mqttClientCon->mqtt_state.out_buffer != NULL) {
// os_free(mqttClientCon->mqtt_state.out_buffer);
// mqttClientCon->mqtt_state.out_buffer = NULL;
// }
if (mqttClientCon->mqtt_state.outbound_message != NULL) {
if (mqttClientCon->mqtt_state.outbound_message->data != NULL) {
os_free(mqttClientCon->mqtt_state.outbound_message->data);
// Don't think, this is has ever been allocated separately
// os_free(mqttClientCon->mqtt_state.outbound_message->data);
mqttClientCon->mqtt_state.outbound_message->data = NULL;
}
}
*/
if (mqttClientCon->mqtt_state.mqtt_connection.buffer != NULL) {
// Already freed but not NULL
mqttClientCon->mqtt_state.mqtt_connection.buffer = NULL;

15
scripts/script.adc 100644
Wyświetl plik

@ -0,0 +1,15 @@
% Config params, overwrite any previous settings from the commandline
% Nothing here
% Now the events, checked whenever something happens
on init
do
settimer 1 1000
on timer 1
do
println "ADC value: " | $adc
settimer 1 1000

Wyświetl plik

@ -16,6 +16,10 @@
#endif
#endif
#ifdef ADC
#include "adc.h"
#endif
#ifdef JSON_PARSE
#include "json_path.h"
#endif
@ -1340,6 +1344,18 @@ int ICACHE_FLASH_ATTR parse_value(int next_token, char **data, int *data_len, Va
*data_type = STRING_T;
return next_token + 1;
}
#endif
#ifdef ADC
else if (is_token(next_token, "$adc")) {
static char adcbuf[8];
lang_debug("val $adc\r\n");
os_sprintf(adcbuf, "%d", adc_read());
*data = adcbuf;
*data_len = os_strlen(*data);
*data_type = STRING_T;
return next_token + 1;
}
#endif
else if (my_token[next_token][0] == '$' && my_token[next_token][1] != '\0') {
lang_debug("val var %s\r\n", &(my_token[next_token][1]));

Wyświetl plik

@ -20,7 +20,14 @@
#define MQTT_CLIENT 1
//#define MQTT_SSL_ENABLE 1
//
// Change this to adjust memory consuption of one MQTT connection
// MQTT_BUF_SIZE is the max. size of pending inbound messages for one connection
// QUEUE_BUFFER_SIZE is the max. size of all pending outbound messages for one connection
//
#define MQTT_BUF_SIZE 1024
#define QUEUE_BUFFER_SIZE 2048
#define MQTT_KEEPALIVE 120 /*seconds*/
#define MQTT_RECONNECT_TIMEOUT 5 /*seconds*/
//#define PROTOCOL_NAMEv31 /*MQTT version 3.1 compatible with Mosquitto v0.15*/
@ -47,21 +54,18 @@
//
// Define this if you want to have GPIO OUT support in scripts.
// Define GPIO_PWM if you want to have additionally GPIO PWM support in scripts.
//
#define GPIO 1
//
// Define this if you want to have additionally GPIO PWM support in scripts.
//
#define GPIO_PWM 1
//
// Define this if you want to have NTP support.
// Define this if you want to have ADC support.
//
#define NTP 1
#define ADC 1
//
// Define this if you want to have HTTP client support.
// Define this if you want to have HTTP client support in scripts.
// Define HTTPCS if you want to have additional HTTPS support.
//
#define HTTPC 1
@ -72,6 +76,11 @@
//
#define JSON_PARSE 1
//
// Define this if you want to have NTP support.
//
#define NTP 1
//
// Define this if you want to have mDNS support.
//

Wyświetl plik

@ -1626,7 +1626,7 @@ void user_init() {
// Start the broker only if it accessible
if (config.mqtt_broker_access != 0) {
espconn_tcp_set_max_con(10);
espconn_tcp_set_max_con(15);
os_printf("Max number of TCP clients: %d\r\n", espconn_tcp_get_max_con());
MQTT_server_onData(MQTT_local_DataCallback);