Tuesday, March 24, 2015

Quick Notes #1

In the latest SKD 1.0.0 I've seen an interesting function:

system_update_cpu_freq

Function:  Set CPU frequency. Default is 80MHz.

Prototype:

bool system_update_cpu_freq(uint8 freq)

Parameter:

uint8 freq : CPU frequency
#define SYS_CPU_80MHz     80
#define SYS_CPU_160MHz 160

Return:
true:  succeed

false: fail

which is nice, you can double the speed.

Post man #3


From time to time you will need to check the signal on some pins. For that I've recommend you a logical analyzer like this one from banggood.com  (affiliate link)


Specs:


Sampling rate up to: 24 MHz
The logic for each channel sampling rate of 24M / s. General applications around 10M, enough to cope with a variety of occasions.

8-channel:
Logic eight inputs - can be collected at the same time they signal analysis, such as I2C, UART, sampling and analysis.

10 billion samples:
The logic can sample up to 100 100 million everything, so you capture even the most elusive events.

Voltage range:
0.8V logic: 5V voltage, to accept the 5.25 V standard CMOS threshold logic low. 2.0 V logic high. The input impedance is approximately 1 MΩ to see more specificati$

Protection:
Support for the latest version: 1.1.30 version

Note:

You can also download the driver from the link:
www.mcu123.com/product/saleae/Saleae_24M_CD.RAR
Software for learning www.saleae.com doesn't do any other purposes.

Package included:

1 x 24M 8CH logic analyzer
10 x Color DuPont line (10 different color)
1 x USB-MINI line 1

Wires left floating sometimes produce garbage data, so if, say you're only using 4 of the data lines, tie the other 4 to ground so they will show as 0 in the program

Analyzer connected to a PIR sensor

After I've installed the 1.1.15 version for 64 bits and quickly connected a PIR on DCH0 I was able to see the signal in application. Off-course,  this analyzer can do more than that, but it was a quick check to let the shop know that the product is working. 

Saleae 1.1.15 connected to a PIR

New SDK version ( 1.0 )

Espressif the producer of the ESP8266EX chip has announces availability of a new SDK.

If you want to download the latest SDK click here.

So, current version now is 1.0.

Fix bugs:
1     Interrupt during flash erasing will cause wdt reset;
2     Read/write rtc memory;
3     If router disconnect to ESP8266, ESP8266 won’t reconnect;
4     Connect to router which has its SSID

Add APIs:
1 system_update_cpu_freq: change CPU frequency;
2 wifi_promiscuous_set_mac: set a mac address filter during sniffer;
3 wifi_set_broadcast_if : set which interface will UDP broadcast send from;

Optimization:
1 Optimize smartconfig to version v1.0;Please don't call any other APIs during SmartConfig.
2 Optimize AT to version 0.22.0.0;
3 Optimize the protection of system parameters , and add error-check about it;
4 Optimize beacon delay of ESP8266 softAP;
5 Optimize boot to version 1.3(b3);
   5.1 Add API system_restart_enhance: for factory test, support to load and run program in any specific address;
   5.2 Add APIs to get boot version and start address of current user bin;
   5.3 Fix compatibility problem of dual flash;
6 Optimize sniffer, structure sniffer_buf changed, please refer to document;
7 Optimize espconn;
8 Optimize pwm;
9 Other optimize to make the software more reliable;


Espressif will give  a minimum of 200 USD for any developer reporting a previously unknown bug in latest Version 1.0. For more info on bug bounty program click here.

Sunday, March 22, 2015

Attention on mounting DHT11 sensor

If you have this development board and you want to mount the DHT11 temperature and humidity sensor that came with the board, you should NOT mount it like in the picture you will find on ebay or other sites. It is wrong and you have the chance to burn some parts of the board.

Again the sensor must mount with the holes/grilles facing the ESP201 board NOT like in the picture.


WRONG WAY TO MOUNT DHT11 SENSOR


THE CORRECT WAY IS LIKE IN THIS PICTURE.

CORRECT WAY TO MOUNT DHT11 SENSOR.

Be careful, search or ask first if you don't know.

Friday, March 20, 2015

Publish data from your ESP8266 to thingspeak.com

On this posts ( post#1, post#2) I've presented how to create a channel, fields, API KEYS on thingspeak.com

Now will publish some data from ESP8266 to thingspeak.com. Can be any kind of data, from
temperature, humidity, voltage you name it. As long as it has a value, can be published.

Add following  lines after the include statements. (Can use the blinky code as skeleton).

#include "espconn.h" 
LOCAL struct espconn *pCon = NULL;
LOCAL my_count = 0;
LOCAL your_value = 33;




Add the following code in the user_init() function.

const char ssid[32] = "my_home_ssid";
const char password[32] = "my_home_password";

struct station_config stationConf;

wifi_set_opmode( STATION_MODE );
os_memcpy(&stationConf.ssid, ssid, 32);
os_memcpy(&stationConf.password, password, 32);
wifi_station_set_config(&stationConf); 
wifi_station_connect();
//connect to the previous pCon created structure
int ret = 0;
ret = espconn_connect(pCon);

if(ret == 0) 
      INFO("espconn_connect OK!\r\n");
else
{
      //INFO("espconn_connect FAILED!\r\n");  
      char *fail;
      os_sprintf(fail, "%d \r\n", ret);
      //INFO(fail);
      //clean up allocated memory
      if(pCon->proto.tcp)
          os_free(pCon->proto.tcp);
      os_free(pCon);
      pCon = NULL;


Add this code in a timer function like in this example:

pCon = (struct espconn *)os_zalloc(sizeof(struct espconn));
if (pCon == NULL)
{
        os_printf("pCon ALLOCATION FAIL\r\n");
        return;
}

pCon->type = ESPCONN_TCP;
pCon->state = ESPCONN_NONE;
    
pCon->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));
pCon->proto.tcp->local_port = espconn_port();
//set up the server remote port
pCon->proto.tcp->remote_port = 80;

//set up the remote IP
uint32_t ip = ipaddr_addr("184.106.153.149"); //IP address for thingspeak.com
os_memcpy(pCon->proto.tcp->remote_ip, &ip, 4);

//set up the local IP
struct ip_info ipconfig;
wifi_get_ip_info(STATION_IF, &ipconfig);
os_memcpy(pCon->proto.tcp->local_ip, &ipconfig.ip, 4);

//register publish_thingspeak_connect_cb that will be called when the
//connection with the thingspeak is done. In this call back function
// will actualy do the data sending
espconn_regist_connectcb(pCon, publish_thingspeak_connect_cb);



where the callback function is:


static void ICACHE_FLASH_ATTR publish_thingspeak_connect_cb(void *arg)
{
  //INFO("========>publish_thingspeak_connect_cb\r\n");
  my_count++;

  struct espconn *pespconn = (struct espconn *)arg;

  char payload[128];

  char field1[10];
  char field2[10];

  os_sprintf(field1, "%d", your_value);
  os_sprintf(field2, "%d", my_count);

  os_sprintf(payload, "GET /update?  api_key=YOUR_THINGSPEAK_API_KEY&field1=%s&field2=%s\r\n", field1, field2);

  espconn_sent(pespconn, payload, strlen(payload));
  
}

and need to be added before the user_main function.

Change my_count and your_value with your data. 

Notes:

1. The time between to posts on thingspeak.com must be greater then 15 seconds.
2. Up to 8 fields can be used to post data on thingspeak.com





Thursday, March 19, 2015

Example: Blink a LED

Like in the Arduino case one of the first thinks to try it is to blink an LED.

The following link contains the code for blink an LED.

Materials:

  • ESP-01 - or other version 
  • LED 
  • SERIAL to USB

If you have my setup described here 

1. put the the archive into this directory

/opt/Espressif/ESP8266_SDK   

2. untar the file

tar -xvf blinky.tar

3. enter in the app directory

cd blinky

4. compile the code

make clean ; make.

5. Upload the resulting files ( from the firmware directory) to your ESP after this steps

5.1 Unplug the VCC power pin
5.2 Connect the GPIO0 pin to ground
5.3.Use the command to write the firmware

./burnESP


Anatomy of the code

 The main application file is the user_main.c file located in 
/opt/Espressif/ESP8266_SDK/blinky/user

The file content is:


#include "ets_sys.h"
#include "osapi.h"
#include "gpio.h"
#include "os_type.h"
#include "user_config.h"

#define user_procTaskPrio        0
#define user_procTaskQueueLen    1
os_event_t    user_procTaskQueue[user_procTaskQueueLen];
static void user_procTask(os_event_t *events);

static volatile os_timer_t some_timer;


void some_timerfunc(void *arg)
{
    //Do blinky stuff
    if (GPIO_REG_READ(GPIO_OUT_ADDRESS) & BIT2)
    {
        //Set GPIO2 to LOW - TURN OFF the LED
        gpio_output_set(0, BIT2, BIT2, 0);
    }
    else
    {
        //Set GPIO2 to HIGH - TURN ON the LED
        gpio_output_set(BIT2, 0, BIT2, 0);
    }
}

//Do nothing function
static void ICACHE_FLASH_ATTR  user_procTask(os_event_t *events)
{
    os_delay_us(10);
}

//Init function 
void ICACHE_FLASH_ATTR user_init()
{
    // Initialize the GPIO subsystem.
    gpio_init();

    //Set GPIO2 to output mode
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2);

    //Set GPIO2 low
    gpio_output_set(0, BIT2, BIT2, 0);

    //Disarm timer
    os_timer_disarm(&some_timer);

    //Setup timer
    os_timer_setfn(&some_timer, (os_timer_func_t *)some_timerfunc, NULL);

    //Arm the timer, &some_timer is the pointer 1000 is the fire time in ms
    //0 for once and 1 for repeating timer
    os_timer_arm(&some_timer, 1000, 1);
    
    //Start os task
    system_os_task(user_procTask, user_procTaskPrio,user_procTaskQueue, user_procTaskQueueLen);
}


and is pretty much self explanatory.

1. Include the necessary headers. See that user_config.h is empty so if you can use this app as a skeleton for your future applications. 

2. In user_init() function the GPIO is initialized, GPIO2 is set up as an output pin and is set
to 0 (LOW, GND).

3. A timer is defined (some_timer) and initialized and the  callback function is set to be called every 1000ms (1sec) interval. 

4. Callback function some_timerfunc is doing all the stuff, if the LED is ON turn it to OFF,
otherwise turn the LED ON.


If you want to add extra functionality check this post for how to have arduino like functions
to manipulate your GPIO. 

Happy codding !!! 

Tuesday, March 17, 2015

Post man #2 - USB Sound Cards

      To complete the system for IoT Home Automation I've ordered on alliexpress few weeks ago two USB sound cards. 

They are like a US$1.20/pcs, so is not bad. According to the seller, specs are:

Features:
USB 2.0 Audio Headset Microphone Jack Converter Adapter
New generic USB2.0 to Audio Adapter w/ Microphone Jack, Gray
Real USB Plug & Play, eliminates the need of traditional sound card!!!
The audio adapter is the best entertainment for Game, DVD, Music
Instantly creates microphone in & audio out jack from any PC / PS3 USB port
No need to reach behind your PC for audio jacks
Compensates any desktop speakers with 3.5mm headphone jack
USB powered, no external power required
the USB sound Adapter support 3D positional sound and virtual 5.1 CH sound Track
Dynamic surround background sound effects
Digital Class-B Power Amplifier Inside
This USB Audio Adapter support Windows 98/2000 / Me / XP / Vista / 7, for OS Mac 8.6 Above


USB sound card



I've connected one of them to my old raspberry pi and the Internet Radio mpd is working perfect. Of course that raspberry pi is having audio output on 3.5mm jack and on HDMI, but I am interested in microphone input. 

Test for vocal command were great using an old USB video camera. Vocal commands were translated in MQTTcommands and I was able to control few LEDs ( to turn them on and off) or to control the Internet Radio ( mpd) or using the text to speech to find what song is playing on radio.

Here is the USB sound card plugged into my raspberry pi:


USB sound card on Raspberry PI










Thursday, March 12, 2015

Arduino function for ESP8266

        If programming the GPIO is hard for you as a beginner but you are familiar with Arduino functions, the following functions can be used as have the same name as in the Arduino IDE.

First define some data in an .h file.

#define HIGH 0x1
#define LOW 0x0
#define INPUT 0x1
#define OUTPUT 0x0
                                                   /*   GPIO | SDK board    |       */
                                                   /*   --------------------|       */
int gpio_pin_register[16] = {PERIPHS_IO_MUX_GPIO0_U,    // 0  gpio 0        | 
                             PERIPHS_IO_MUX_U0TXD_U,    // 1  gpio 1        | 
                             PERIPHS_IO_MUX_GPIO2_U,    // 2  gpio 2        | 
                             PERIPHS_IO_MUX_U0RXD_U,    // 3                |
                             PERIPHS_IO_MUX_GPIO4_U,    // 4  gpio 4        | 
                             PERIPHS_IO_MUX_GPIO5_U,    // 5  gpio 5 buzzer | 
                             PERIPHS_IO_MUX_SD_CLK_U,   // 6                |
                             PERIPHS_IO_MUX_SD_DATA0_U, // 7                |
                             PERIPHS_IO_MUX_SD_DATA1_U, // 8                |
                             PERIPHS_IO_MUX_SD_DATA2_U, // 9  gpio 9        | 
                             PERIPHS_IO_MUX_SD_DATA3_U, // 10 gpio 10       | 
                             PERIPHS_IO_MUX_SD_CMD_U,   // 11               |
                             PERIPHS_IO_MUX_MTDI_U,     // 12 gpio12  blue  | 
                             PERIPHS_IO_MUX_MTCK_U,     // 13 gpio13  green | 
                             PERIPHS_IO_MUX_MTMS_U,     // 14 gpio14  white | 
                             PERIPHS_IO_MUX_MTDO_U};    // 15 gpio15  red   | 
                             

#define GPIO_PIN_ADDR(i)    (GPIO_PIN0_ADDRESS + i*4)


Now the Arduino like functions can be added:

/********************************************************************
* FunctionName: pinMode
* Description : set up a pin mode.
* Parameters  : pin: pin mumber
*             : mode 0 for OUTPUT or 1 for INPUT
*             : pullup 0 for pullup DISABLED and 1 for pullup ENABLED
*             : pulldown not yet supported
* Returns     : None                                                     
*********************************************************************/

void ICACHE_FLASH_ATTR pinMode(uint8_t pin, uint8_t mode, uint8_t pullup) {
    if ((0x1 << pin) & 0b110101) {
        PIN_FUNC_SELECT(gpio_pin_register[pin], 0); //0,2,4,5
    } else {
        PIN_FUNC_SELECT(gpio_pin_register[pin], 3);
    }
    PIN_PULLDWN_DIS(gpio_pin_register[pin]);
    if(pullup)
      PIN_PULLUP_EN(gpio_pin_register[pin]);
    else  
      PIN_PULLUP_DIS(gpio_pin_register[pin]);
    if (mode) {
        GPIO_REG_WRITE(GPIO_ENABLE_W1TC_ADDRESS, 1<<pin); // GPIO input
    } else {
        GPIO_REG_WRITE(GPIO_ENABLE_W1TS_ADDRESS, 1<<pin); // GPIO output
    }
}


Example:
pinMode(0, OUTPUT, 0); //is setting the GPIO 0 as an OUTPUT with pullup disabled

If you want to control also the pulldown add an extra parameter and call the 
PIN_PULLDWN_DIS(gpio_pin_register[pin])for disable and PIN_PULLDWN_EN(gpio_pin_register[pin])for pulldown enable.


Next function are the well known Arduino function for read and write:

/********************************************************************
* FunctionName: digitalWrite
* Description : use to set up HIGH or LOW on a GPIO pin
* Parameters  : pin: pin mumber
*             : state HIGH or LOW
* Returns     : None                                                     
*********************************************************************/

void ICACHE_FLASH_ATTR 
digitalWrite(uint8_t pin, uint8_t state) {
    if (state) {
        GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, 1<<pin); // set GPIO pin high
    } else {
        GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, 1<<pin); // set GPIO pin low
    }
}
/********************************************************************
* FunctionName: digitalRead
* Description : use to set up HIGH or LOW on a GPIO pin
* Parameters  : pin: pin mumber
* Returns     : 1 if pin is HIGH or 0 if pin is LOW                                                     
*********************************************************************/

int ICACHE_FLASH_ATTR 
digitalRead(uint8_t pin) {
    return (GPIO_REG_READ(GPIO_OUT_ADDRESS)>>pin) & 1;
}



Example:

digitalWrite(0, HIGH); //set HIGH the GPIO 0 pin

int gpio_state = digitalRead(0); will return 1 if the GPIO 0 pin's is HIGH or 0 if is LOW

If you save your .h file in the include directory, just use #include "your_file_name.h" in your user_main.c.


For controlling GPIO16 see this post.








Tuesday, March 10, 2015

Usefull tools #2

If you want a nice gauge to display some data you can use the google's one with the help from thingspeak.com.


Thingspeak.com Plugin

For this gauge we will need to read data from thingspeak.com and this require an API Read Key that can be generated from the API KEYS menu.



Now go to the Plugin menu from the Main Menu:



and click on "New Plugin"


and select the Google Gauge and "Create Plugin".

Now you can modify the Javascript with your channel id and the READ API Key:


  // set your channel id here
  var channel_id = 87654;
  // set your channel's read api key here if necessary
  var api_key = 'Q68B3YMORI9S49JJ';
  // maximum value for the gauge
  var max_gauge_value = 100;
  // name of the gauge

  var gauge_name = 'My_gauge_name';

To include the new created gauge in other page you can use the HTML TAG <IFRAME>.

<iframe width="330" height="360" style="border: 1px solid #cccccc;" src="http://api.thingspeak.com/plugins/2345" ></iframe>



Post man #1 - 3V3 relays board

Today I've received a new order from aliexpress.com.

A board with four relays working on 3V3.




I will use the relays to control the irrigation system that is now driven by a Raspberry Pi.

So, the ESP201 will replace the Raspberry Pi that did a very good job in the last three years.

I am using the 3V3 relays just for fun, I've tested the ESP201 with 5V relays and are working normally from my point of view.  



ESP201 dev board - One more finding #2.



Perfect ! The last piece of puzzle was found. How to control the relay on the ESP201 development board.

The on board relay is connected to DIP J, and to GPIO16. In order to trigger GPIO16 you need the function from gpio16.c from IoT Demo.


#include "ets_sys.h"#include "osapi.h"#include "driver/gpio16.h"
void ICACHE_FLASH_ATTRgpio16_output_conf(void){    WRITE_PERI_REG(PAD_XPD_DCDC_CONF,                   (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | (uint32)0x1); // mux configuration for XPD_DCDC to output rtc_gpio0
    WRITE_PERI_REG(RTC_GPIO_CONF,                   (READ_PERI_REG(RTC_GPIO_CONF) & (uint32)0xfffffffe) | (uint32)0x0); //mux configuration for out enable
    WRITE_PERI_REG(RTC_GPIO_ENABLE,                   (READ_PERI_REG(RTC_GPIO_ENABLE) & (uint32)0xfffffffe) | (uint32)0x1); //out enable}
void ICACHE_FLASH_ATTRgpio16_output_set(uint8 value){    WRITE_PERI_REG(RTC_GPIO_OUT,                   (READ_PERI_REG(RTC_GPIO_OUT) & (uint32)0xfffffffe) | (uint32)(value & 1));}
void ICACHE_FLASH_ATTRgpio16_input_conf(void){    WRITE_PERI_REG(PAD_XPD_DCDC_CONF,                   (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | (uint32)0x1); // mux configuration for XPD_DCDC and rtc_gpio0 connection
    WRITE_PERI_REG(RTC_GPIO_CONF,                   (READ_PERI_REG(RTC_GPIO_CONF) & (uint32)0xfffffffe) | (uint32)0x0); //mux configuration for out enable
    WRITE_PERI_REG(RTC_GPIO_ENABLE,                   READ_PERI_REG(RTC_GPIO_ENABLE) & (uint32)0xfffffffe); //out disable}
uint8 ICACHE_FLASH_ATTRgpio16_input_get(void){    return (uint8)(READ_PERI_REG(RTC_GPIO_IN_DATA) & 1);}

and the h file.

#ifndef __GPIO16_H__#define __GPIO16_H__
void gpio16_output_conf(void);void gpio16_output_set(uint8 value);void gpio16_input_conf(void);uint8 gpio16_input_get(void);
#endif


Now, during the init gpio part I can call the gpio16_output_conf to setup the GPIO16 as an output GPIO type.

Programmatic now I can call gpio16_output_set (0) or gpio16_output_set(1) to trigger the onboard realy OFF or ON. 

Again, this is the board I am using for testing and development.



Sunday, March 8, 2015

Problems reading VCC



In the SDK there is a hidden function called readvdd33() that returns the internal measured VDD.


000004f8 T readvdd33

On my setup board I am not able to find a correct value since the function always returns 4096. Need to test it on the ESP-01 to see if make any difference.


Update: Other users have reported this function as a working one, maybe their setup was running on batteries ?

Will be nice to have this functions like it is on Arduino ! 

ESP201 dev board - One more finding #1.


Good news today!

I have managed to find why the GPIO15 connected to the RED RGB LED was not working !

The answer was under my nose. DIP pin K1 (S2) must be on the OFF position. See the picture:



Cool !!!! Now I can fully test PWM on this board.





Remaining unknown items: RELAY (J) connected to GPIO16.  SOLVED !!! See link below.

UPDATE: triggering the relay is described here

Thursday, March 5, 2015

Usefull tools #1






Ok, we have the board, we have the environment but we need to see the values from the sensors as a nice graph. What we should do ?

For storing the values I recommend and I use thingspeak.com.

Make an account on thingspeak.com and create a new channel.



Complete the fields for the newly created channel, a channel name, a description, metadata,
tags, Make Public check box.



On this step important fields are ones labeled Field 1 to Field 8. You can use them later 
to insert values into the thingspeak database. So complete the labels that your values will have.




Save your channel so you can use it later. You can come back later and modify those values.



API KEY

In order to upload values to thingspeak.com from the ESP8266, match must be done between your account and your ESP8266. This is done by the API KEY which can be found in the API KEYS menu.

Keep this KEY secret and don't post it on the web as I've seen it in a lot of github code. Every one that know you API KEY can alter your values and you will bang your head on the tables to see why your temperature is 200 degrees.  



Don't bother to use the API KEY above, I'll delete the channel later.


Testing

It's time to test the channel and the api key.

For now just add the the link changing the API_KEY with your own value in a browser.

http://api.thingspeak.com/update?key=[API_KEY]&field1=22&field2=55

which in my case is 

http://api.thingspeak.com/update?key=UD05NUCXSTSJ39W&field1=22&field2=55

Don't panic if your browser will show you just a blank page with one value "1", is the id
for your first record inserted into the database.





If you are going back the the channel page, you will see the values for field1 (temperature) and field2(humidity). In this way you can update up to 8 values in one shot.

Temperature:



Humidity:



Note: Keep at least 15 seconds between two writes !