Tensilica es una compañía fundada en 1997 pero que en los últimos tiempos viene sorprendiendo con sus nuevos procesadores y en particular por el alto grado de integración de periféricos. 
Tomando como ejemplo el Xtensa LX6 con dos núcleos de 32 bits y donde todo está a bordo. ESP32 tiene este procesador y es considerado una evolución del popular ESP8266 de amplio uso en el mundo de los microcontroladores.

  • 18 Canales ADC.
  • 3 SPI.
  • 2 I2C.
  • 2 I2S.
  • 3 UART.
  • 16 Salidas PWM para manejo de LEDs.
  • 2 DAC.
  • 10 Entradas Touch Capacitivas.
  • Sensor Hall.
  • Sensor de temperatura.
  • Host para el control de memorias SD/SDIO/MMC.
  • Bus CAN.
  • Puertos GPIO.
  • WiFi.
  • Bluetooth.
  • Y varias cosas mas!!!!

Dos núcleos operando a 240 Mhz que pueden trabajar en forma cooperativa o independiente. Todo compatible con ARM y siguiendo la misma filosofía de programación como se puede ver en el siguiente código para leer un canal analógico.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/******************************************************************************
**  Descripción  : Uso del conversor A/D usando ADC_0 (GPIO36)                
**  Target       : Tensilica Xtensa LX6 Dual Core 240 Mhz
**  ToolChain    : Esp-Idf
**  www.firtec.com.ar
*******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "driver/adc.h"
 
#define ADC1 (0)
 
void tarea_adc1(void* arg)
{
    unsigned int dato;
    // Configura el ADC
    adc1_config_width(ADC_WIDTH_12Bit);
    adc1_config_channel_atten(ADC1,ADC_ATTEN_11db);
    while(1){
		dato = adc1_get_raw(ADC1_CHANNEL_0);
		printf("ADC = %d\n",dato);
		vTaskDelay(1000/portTICK_PERIOD_MS);
    }
}
 
void app_main()
{
    xTaskCreate(tarea_adc1, "tarea_adc1", 1024*3, NULL, 10, NULL);
}

 

Tener mas de una CPU lleva el trabajo con microcontroladores a otro nivel donde el concepto de multitarea se hace realidad.
En los ejemplos estuvimos probando la placa SparkFun ESP32 Thing con resultados realmente muy interesantes.
Para construir una aplicación completa no necesitamos agregar ningún microcontrolador. ES32 tiene todo lo necesario incluso conectividad WiFi y algo por demás interesante es que podemos trabajar directamente con el entorno de Arduino.
En este ejemplo se ha instalado un servidor MQTT en una placa Raspberry PI y el siguiente código en  ESP32 programado mediante el IDE de Arduino, el ejemplo solo lee el sensor HDC1000 conectado al puerto I2C del ESP32 y publica los datos en una red MQTT.
A su vez ESP32 publica en la red el control de un LED que la propia placa trae a bordo, los clientes con acceso al tópico pueden controlar el estado del LED.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/********************************************************* 
 *  ESP32 cumple con dos tareas: 
 *  1- Leer datos desde un sensor HDC1000.
 *  2- Controlar el encendido y apagado de LED en GPIO_5
*********************************************************/
 
#include <WiFi.h>
#include <PubSubClient.h>
#include "HDC1000.h"
HDC1000 hdc1000;
 
char Temperatura[5];
char Humedad[7];
 
const char* ssid     = "Fibertel_Firtec";
const char* password = "Aula_1";
 
// IP del servidor MQTT (Raspberry P)
const char* mqtt_server = "192.168.0.124";
 
float t = 0.0, h = 0.00;
boolean bandera = false;
 
// Crea una instancia del cliente PubSubClient
WiFiClient espClient;
PubSubClient client(espClient);
 
// GPIO_5 pin del LED
const char led = 5;
 
// Se definen los topicos o temas
#define TEMP_TOPIC   "firtec/dato1/temp"
#define HUM_TOPIC    "firtec/dato1/hum"
#define LED_TOPIC    "firtec/dato1/led" // 1 SI 0 NO
 
long lastMsg = 0;
 
// Decodifica el mensaje publicado desde el movil
void receivedCallback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Recibido: ");
  Serial.println(topic);
 
  Serial.print("payload: ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  /* we got '1' -> on */
  if ((char)payload[0] == '1') {
    digitalWrite(led, HIGH);  // Si es 1 encender el LED
  } else {
    /* we got '0' -> on */
    digitalWrite(led, LOW);  // Si es 0 apagar el LED
  }
 
}
 
void mqttconnect() {
  // Bucle de conexión
  while (!client.connected()) {
    Serial.print("MQTT conectando ...");
    // ID del cliente
    String clientId = "ESP32Client";
   
    if (client.connect(clientId.c_str())) {
      Serial.println("conectado!!");
      // Subscribir al tipico con QoS 0
      client.subscribe(LED_TOPIC);
    } else {
      Serial.print("Error, status code =");
      Serial.print(client.state());
      Serial.println("Intentar de nuevo en 5 segundos");
      delay(5000);
    }
  }
}
 
void setup() {
  Serial.begin(9600);
  Serial.println();
  Serial.print("Conectando con ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print("*");
  }
  // Configura el pin del LED como salida
  pinMode(led, OUTPUT);
 
  Serial.println("");
  Serial.println("WiFi conectado");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
 
  // Configura le IP del servidor y el puerto MQTT
  client.setServer(mqtt_server, 1883);
  /* Funcion receivedCallback que sera invocada cuando 
     el cliente reciba info de un subscripto */
  client.setCallback(receivedCallback);
  hdc1000.begin();
  //dht.begin();
}
void loop() {
  // Si un cliente se desconecta esperar hasta que reconecte
  if (!client.connected()) {
    mqttconnect();
  }
  
  client.loop();
  /* Medir cada tres segundos, NO usar delay() puesto que esta es
     una funcion bloqueante */
  long now = millis();
  if (now - lastMsg > 3000) {
    if(bandera == false) {
    lastMsg = now;
    t = hdc1000.getTemperature();     
         if (t == HDC1000_ERROR_CODE) {
                hdc1000.begin(); // retry once
                t = hdc1000.getTemperature();
          }
     dtostrf(t, 2, 1, Temperatura);
     Serial.println(Temperatura);
     //snprintf (msg, 20, "%2.1f", t);   
     client.publish(TEMP_TOPIC, Temperatura); 
     bandera = true; 
    }
    else {
      lastMsg = now;
      h = hdc1000.getHumidity();
 
          if (h== HDC1000_ERROR_CODE) {
           do{    
                hdc1000.begin(); 
                 h = hdc1000.getHumidity();
           }while(h > 100);       
          }
      dtostrf(h, 3, 1, Humedad);
      Serial.println(Humedad);
      //snprintf (msg, 20, "%3.1f%%", h);    
      client.publish(HUM_TOPIC, Humedad);
      bandera = false;
      }
     } 
    }

 El resultado es el siguiente.


La programación para el ESP32 se trata en el curso de IOT.