Post Reply 
 
Thread Rating:
  • 2 Votes - 4.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Only You, or ESP8266 Forever!
05-15-2016, 09:58 AM
Post: #12
RE: Only You, or ESP8266 Forever!
(05-15-2016 08:20 AM)michael_s Wrote:  Начал собирать плату , подключил esp + drv8825 + mpu6050.
При старте на esp12 загорается светодиод, появляется wifi сеть и двигатель находится в режиме удержания (сопротивляется ручному повороту).
Робот должен после старта сам начать балансировать или же необходимо через софт его оживить ?

Кстати я так понимаю что программа OSCillation от iWork не позволит ползунки возвращать в исходное состояние при отпускании пальцев ? TouchOSC нынче неплохо так стоит денег Smile
Огрехи отладки дают о себе знать...
Замените содержимое файлов:
eX_ESP_Timing_Engine.h
Code:
#ifndef _ESP_TIMING_ENGINE_H_
#define _ESP_TIMING_ENGINE_H_

#define PIN_READ(x)           ((GPI & (1 << x)) != 0)
#define PIN_LOW(x)            (GPOC = (1 << x))
#define PIN_HIGH(x)           (GPOS = (1 << x))
#define SONAR_TRIG_PIN_LOW()  (GP16O &= ~1)
#define SONAR_TRIG_PIN_HIGH() (GP16O |= 1)

#define NUM_DEV  4
#ifdef USE_2_SERVOS
  #define NUM_DEV  5
#endif
///  Переменные подпрограмм управления моторами ///
int16_t    speed_M1, speed_M2;        // текущая скорость вращения моторов
int32_t    echo_start, echo_stop, echo_value=1000000;

typedef struct {
  int8_t         phase_or_dir;
  int32_t        a_period;
  int32_t        b_period;
  int32_t        c_period;
} device_header_t;

device_header_t  devices[NUM_DEV];


// Переопределение функций прерывания, которых нет в ранних версиях API

#define xt_rsil(level) (__extension__({uint32_t state; __asm__ __volatile__("rsil %0," __STRINGIFY(level) : "=a" (state)); state;}))
#define xt_wsr_ps(state)  __asm__ __volatile__("wsr %0,ps; isync" :: "a" (state) : "memory")
#define te_write(count) __asm__ __volatile__("wsr %0,ccompare0; esync"::"a" (count) : "memory")

uint32_t te_getCycleCount()
{
    uint32_t ccount;
    __asm__ __volatile__("esync; rsr %0,ccount":"=a" (ccount));
    return ccount;
}

static volatile timercallback te_user_cb = NULL;

void ICACHE_RAM_ATTR te_isr_handler(void* para)
{
    if (te_user_cb)
    {
      uint32_t savedPS = xt_rsil(15); // stop other interrupts
      te_user_cb();
      xt_wsr_ps(savedPS);   // start other interrupts
    }
}

void te_isr_init()
{
    ETS_CCOMPARE0_INTR_ATTACH(te_isr_handler, NULL);
}

void te_attachInterrupt(timercallback userFunc) {
    te_user_cb = userFunc;
    ETS_CCOMPARE0_ENABLE();
}

void te_detachInterrupt() {
    te_user_cb = NULL;
    ETS_CCOMPARE0_DISABLE();
}


void ICACHE_RAM_ATTR te_Processor()
{
uint32_t cc;
  te_write(te_getCycleCount() + 675); // задаем период в 675 тиков таймера для формирования рабочего периода в 10 мкс (340 для 5 мкс)
  PIN_LOW(MOTOR1_STEP_PIN);
  PIN_LOW(MOTOR2_STEP_PIN);
  for(int i=0; i < NUM_DEV; ++i)
  {
    if((--devices[i].a_period) == 0)
    {
      if(i == 0) // обработка шагового двигателя 1
      {
        if(devices[0].phase_or_dir < 0)
        {
          devices[0].a_period = devices[0].c_period;
        }
        else
        {
          devices[0].a_period = devices[0].b_period;
          if(devices[0].phase_or_dir == !PIN_READ(MOTORS_DIR_PIN))
          {
            if(devices[0].phase_or_dir)
            {
              PIN_HIGH(MOTORS_DIR_PIN);             // DIR Motors for Motor1 (Forward)
            }
            else
            {
              PIN_LOW(MOTORS_DIR_PIN);              // DIR Motors for Motor1 (Revers)
            }
            cc = te_getCycleCount();
            while((te_getCycleCount() - cc) < PRE_DIR_STROBE);
          }
          PIN_HIGH(MOTOR1_STEP_PIN);
        }
      }
      else if(i == 1) // обработка шагового двигателя 2
      {
        if(devices[1].phase_or_dir < 0)
        {
          devices[1].a_period = devices[1].c_period;
        }
        else
        {
          devices[1].a_period = devices[1].b_period;
          if(devices[1].phase_or_dir == PIN_READ(MOTORS_DIR_PIN))
          {
            if (devices[1].phase_or_dir)
            {
              PIN_LOW(MOTORS_DIR_PIN);                     // DIR Motors for Motor2 (Revers)
            }
            else
            {
              PIN_HIGH(MOTORS_DIR_PIN);                    // DIR Motors for Motor2 (Forward)
            }
            cc = te_getCycleCount();
            while((te_getCycleCount() - cc) < PRE_DIR_STROBE);
          }
          PIN_HIGH(MOTOR2_STEP_PIN);
        }
      }
      else if(i == 2) // обработка запускающего импульса сонара
      {
        if(devices[2].phase_or_dir)
        {
          SONAR_TRIG_PIN_LOW();
          devices[2].phase_or_dir = 0;
          devices[2].a_period = devices[2].b_period - 1;
        }
        else
        {
          SONAR_TRIG_PIN_HIGH();
          devices[2].phase_or_dir = 1;
          devices[2].a_period = 1;    // длительность положительного строба 10 мкс или 1 период управления
        }
      }
      else if(i == 3) // обработка серво-привода 1
      {
        if(devices[3].phase_or_dir)
        {
          PIN_LOW(SERVO1_PIN);
          devices[3].phase_or_dir = 0;
          devices[3].a_period = devices[3].c_period - devices[3].b_period;
        }
        else
        {
          PIN_HIGH(SERVO1_PIN);
          devices[3].phase_or_dir = 1;
          devices[3].a_period = devices[3].b_period;    // длительность положительного строба
        }
      }
#ifdef USE_2_SERVOS
      else if(i == 4) // обработка серво-привода 2
      {
        if(devices[4].phase_or_dir)
        {
          PIN_LOW(SERVO2_PIN);
          devices[4].phase_or_dir = 0;
          devices[4].a_period = devices[3].c_period - devices[3].b_period;
        }
        else
        {
          PIN_HIGH(SERVO2_PIN);
          devices[4].phase_or_dir = 1;
          devices[4].a_period = devices[3].b_period;    // длительность положительного строба
        }
      }
#endif
    }
  }
}

void ICACHE_RAM_ATTR te_SonarEcho()
{
  if(PIN_READ(SONAR_ECHO_PIN))
  {
    echo_start = te_getCycleCount();
  }
  else
  {
    echo_stop = te_getCycleCount();
    echo_value = echo_stop - echo_start;
  }
}

void te_Start()
{
// Инициируем выходы управления драйверами моторов
  pinMode(MOTORS_ENABLE_PIN,OUTPUT);
  PIN_HIGH(MOTORS_ENABLE_PIN);    // драйвера не активны
  pinMode(MOTORS_DIR_PIN,OUTPUT);
  
// Инициируем motor1 как devices[0]
  pinMode(MOTOR1_STEP_PIN,OUTPUT);
  PIN_LOW(MOTOR1_STEP_PIN);
  devices[0].phase_or_dir = -1;  // -1 - шаг не делать, 0 - шаг назад, 1 - шаг вперёд
  devices[0].a_period = 1;
  devices[0].b_period = ZERO_SPEED;
  devices[0].c_period = ZERO_SPEED;
  
// Инициируем motor2 как devices[1]
  pinMode(MOTOR2_STEP_PIN,OUTPUT);
  PIN_LOW(MOTOR2_STEP_PIN);
  devices[1].phase_or_dir = -1;  // -1 - шаг не делать, 1 - шаг назад, 0 - шаг вперёд (инверсия стгналов управления)
  devices[1].a_period = 1;
  devices[1].b_period = ZERO_SPEED;
  devices[1].c_period = ZERO_SPEED;
  
// Инициируем sonar как devices[2]
  pinMode(SONAR_TRIG_PIN,OUTPUT);
  SONAR_TRIG_PIN_LOW();
  pinMode(SONAR_ECHO_PIN,INPUT);
  attachInterrupt(SONAR_ECHO_PIN, te_SonarEcho, CHANGE);
  devices[2].phase_or_dir = 0;
  devices[2].a_period = 1;
  devices[2].b_period = 4000;    // максимальное значение периода 40 миллисекунд или при длительности периода обработки 10 мкc  - 4000 периодов
// Инициируем servo1 как devices[3]
  pinMode(SERVO1_PIN,OUTPUT);
  PIN_LOW(SERVO1_PIN);
  devices[3].phase_or_dir = 0;
  devices[3].a_period = 1;
  devices[3].b_period = SERVO_AUX_NEUTRO;
  devices[3].c_period = 2000;  
#ifdef USE_2_SERVOS
  // Инициируем servo2 как devices[4]
  pinMode(SERVO2_PIN,OUTPUT);
  PIN_LOW(SERVO2_PIN);
  devices[4].phase_or_dir = 0;
  devices[4].a_period = 1;
  devices[4].b_period = SERVO_AUX_NEUTRO;
  devices[4].c_period = 2000;
#endif
// Запуск таймера
  te_isr_init();
  te_attachInterrupt(te_Processor);
  te_write(te_getCycleCount() + 1500);
}

// Установка скорости вращения моторов
// tspeed_Mx может принимать как положительные, так и отрицательные значения (reverse)
void te_SetMotorsSpeed(int16_t t_speed_M1, int16_t t_speed_M2)
{
  int32_t   speed_1, speed_2;
  // Лимитируем изменение скорости с учётом максимального ускорения для motor1
  if ((speed_M1 - t_speed_M1) > MAX_ACCEL)
    speed_M1 -= MAX_ACCEL;
  else if ((speed_M1 - t_speed_M1) < -MAX_ACCEL)
    speed_M1 += MAX_ACCEL;
  else
    speed_M1 = t_speed_M1;
    
  // Лимитируем изменение скорости с учётом максимального ускорения для motor2
  if ((speed_M2 - t_speed_M2) > MAX_ACCEL)
    speed_M2 -= MAX_ACCEL;
  else if ((speed_M2 - t_speed_M2) < -MAX_ACCEL)
    speed_M2 += MAX_ACCEL;
  else
    speed_M2 = t_speed_M2;

  speed_1 = speed_M1 * K_MOTOR_SPEED;
  speed_2 = speed_M2 * K_MOTOR_SPEED;
// Расчёт периода для motor1
  if (speed_1 == 0)
  {
    devices[0].b_period = ZERO_SPEED;
    devices[0].phase_or_dir = -1;
  }
  else
    if (speed_1 > 0)
    {
      devices[0].b_period = 6400000/speed_1;   // 6400000 - это максимальное значение speed_M1 (max. 500) * K_MOTOR_SPEED (max.12800)
      devices[0].phase_or_dir = 1;
    }
    else
    {
      devices[0].b_period = 6400000/-speed_1;
      devices[0].phase_or_dir = 0;
    }

// Расчёт периода для motor2
  if (speed_2 == 0)
  {
    devices[1].b_period = ZERO_SPEED;
    devices[1].phase_or_dir = -1;
  }
  else
    if (speed_2 > 0)
    {
      devices[1].b_period = 6400000/speed_2;
      devices[1].phase_or_dir = 1;
    }
    else
    {
      devices[1].b_period = 6400000/-speed_2;
      devices[1].phase_or_dir = 0;
    }
}
void te_SetServo(int pwm, int num=0)
{
  if (num == 0)
    devices[3].b_period = pwm;
#ifdef USE_2_SERVOS
  if (num == 1)
    devices[4].b_period = pwm;
#endif
}
#endif // _ESP_TIMING_ENGINE_H_

и
eX_ESP_Robot.ino
Code:
#include <ESP8266WiFi.h>
#include "eX_ESP_Config.h"
#include "eX_ESP_Pins.h"
#include "eX_ESP_WiFi.h"
#include "eX_ESP_OSC.h"
#include "eX_ESP_MPU6050.h"
#include "eX_ESP_Functions.h"
#include "eX_ESP_Timing_Engine.h"

//#include <Arduino.h>
bool       robot_shutdown = false;   // Robot shutdown flag
bool       robot_pro_mode;           // Robot_mode = false - Normal mode, True - Pro mode ()

long       timer_old_value;
long       timer_value;
float      dt;
    
float      bat_level;
float      dist_value;

float      throttle;
float      steering;

float      max_throttle     = MAX_THROTTLE;
float      max_steering     = MAX_STEERING;
float      max_target_angle = MAX_TARGET_ANGLE;
float      Kp               = KP;
float      Kd               = KD;
float      Kp_thr           = KP_THROTTLE;
float      Ki_thr           = KI_THROTTLE;
float      Kp_user          = KP;
float      Kd_user          = KD;
float      Kp_thr_user      = KP_THROTTLE;
float      Ki_thr_user      = KI_THROTTLE;

float      angle_adjusted;            // Angle of the robot (used for stability control)
float      angle_adjusted_Old;
int16_t    actual_robot_speed;        // overall robot speed (measured from steppers speed)
int16_t    actual_robot_speed_Old;    
float      estimated_speed_filtered;  // Estimated robot speed
float      target_angle;
float      control_output;

int16_t    motor1;
int16_t    motor2;

uint16_t   loop_counter = 0;



void setup()
{
#ifdef USE_UART
  Serial.begin(SERIAL_SPEED);
#endif
  WiFi_Start();
  te_Start();
  i2c_begin(SDA_PIN, SCL_PIN, I2C_SPEED);
  timer_old_value = millis();
  robot_pro_mode = false;
  robot_shutdown = false;
  if (mpu_Initialization() == 0)
    robot_shutdown = true;  
  
}

void loop()
{
  if (robot_shutdown)
    return;
  if(OSC_MSG_Read())
  {
    if (page==1)
    {
      if ((!robot_pro_mode)&&(toggle[0]==1))
      {
        // Change to PRO mode
        max_throttle = MAX_THROTTLE_PRO;
        max_steering = MAX_STEERING_PRO;
        max_target_angle = MAX_TARGET_ANGLE_PRO;
        robot_pro_mode = true;    
      }
      if ((robot_pro_mode)&&(toggle[0]==0))
      {
        // Change to NORMAL mode
        max_throttle = MAX_THROTTLE;
        max_steering = MAX_STEERING;
        max_target_angle = MAX_TARGET_ANGLE;
        robot_pro_mode = false;
      }
      // Push reset controls to neutral position
      if (push[1] || ChangePage)
      {
        ChangePage = false;
        fadder[0] = 0.5;
        WiFi_MSG_Send_Float("/1/fader1\0\0\0,f\0\0\0\0\0\0",20,fadder[0]);
        fadder[1] = 0.5;
        WiFi_MSG_Send_Float("/1/fader2\0\0\0,f\0\0\0\0\0\0",20,fadder[1]);
      }

      throttle = (fadder[0] - 0.5) * max_throttle;
      steering = fadder[1] - 0.5;
      if (steering > 0)
        steering = ( steering * steering + 0.5 * steering) * max_steering;
      else
        steering = (-steering * steering + 0.5 * steering) * max_steering;
    }
    else // set Page=2
    {
      throttle = 0;
      steering = 0;
      if (ChangePage)
      {
        ChangePage = false;
        fadder[0] = Kp_user/KP/2;
        WiFi_MSG_Send_Float("/2/fader1\0\0\0,f\0\0\0\0\0\0",20,fadder[0]);
        fadder[1] = Kd_user/KD/2;
        WiFi_MSG_Send_Float("/2/fader2\0\0\0,f\0\0\0\0\0\0",20,fadder[1]);
        fadder[2] = Kp_thr_user/KP_THROTTLE/2;
        WiFi_MSG_Send_Float("/2/fader3\0\0\0,f\0\0\0\0\0\0",20,fadder[2]);
        fadder[3] = Ki_thr_user/(KI_THROTTLE+0.1)/2;
        WiFi_MSG_Send_Float("/2/fader4\0\0\0,f\0\0\0\0\0\0",20,fadder[3]);
      }
      else
      {
        Kp_user = KP*2*fadder[0];
        Kd_user = KD*2*fadder[1];
        Kp_thr_user = KP_THROTTLE*2*fadder[2];
        Ki_thr_user = (KI_THROTTLE+0.1)*2*fadder[3];
      }
      while (toggle[1])
      {
      //Reset external parameters
        mpuResetFIFO();
        PID_errorSum = 0;
        timer_old_value = millis();
        te_SetMotorsSpeed(0,0);
        OSC_MSG_Read();
      }
    }
  }
    // New DMP Orientation solution?
  fifoCount = mpuGetFIFOCount();
  if (fifoCount>=18)
  {
    loop_counter++;
    if (fifoCount>18)
    {
      mpuResetFIFO();
      return;
    }
    timer_value = millis();
    dt = (timer_value - timer_old_value);
    timer_old_value = timer_value;
    angle_adjusted_Old = angle_adjusted;
    // Get new orientation angle from IMU (MPU6050)
    angle_adjusted = dmpGetPhi();

    if ((angle_adjusted<74)&&(angle_adjusted>-74))  // Робот в рабочем ли положении?
    {
      // NORMAL MODE
      // Push1 Move servo arm
      PIN_LOW(MOTORS_ENABLE_PIN);
      if (push[0])  // Move arm
        te_SetServo(SERVO_MIN_PULSEWIDTH+10);
      else
        te_SetServo(SERVO_AUX_NEUTRO);
      if ((angle_adjusted<40)&&(angle_adjusted>-40))
      {
        Kp = Kp_user;            // Получает контроль пользователя по умолчанию
        Kd = Kd_user;
        Kp_thr = Kp_thr_user;
        Ki_thr = Ki_thr_user;
      }    
      else    // Во время поднятия робота в рабочее положение мы используем специальные параметры контроля
      {
        Kp = KP_RAISEUP;         // CONTROL GAINS FOR RAISE UP
        Kd = KD_RAISEUP;
        Kp_thr = KP_THROTTLE_RAISEUP;
        Ki_thr = KI_THROTTLE_RAISEUP;
      }
    }
    else   // Robot not ready (flat), angle > 70º => ROBOT OFF
    {
      PIN_HIGH(MOTORS_ENABLE_PIN);
      PID_errorSum = 0;  // Reset PID I term
      Kp = KP_RAISEUP;   // CONTROL GAINS FOR RAISE UP
      Kd = KD_RAISEUP;
      Kp_thr = KP_THROTTLE_RAISEUP;
      Ki_thr = KI_THROTTLE_RAISEUP;

      // if we pulse push1 button we raise up the robot with the servo arm
      if (push[0])
      {
        // Because we know the robot orientation (face down of face up), we move the servo in the appropiate direction for raise up
        if (angle_adjusted>0)
          te_SetServo(SERVO_MIN_PULSEWIDTH);
        else
          te_SetServo(SERVO_MAX_PULSEWIDTH);
      }
      else
        te_SetServo(SERVO_AUX_NEUTRO);

    }

      // Мы рассчитываем расчетную скорость робота
      // Расчетная скорость = угловая скорость шаговых двигателей (в сочетании) - угловая скорость робота (угол измеряется IMU)
    actual_robot_speed_Old = actual_robot_speed;
    actual_robot_speed = (speed_M1 + speed_M2)/2;                                           // Positive: forward
    int16_t angular_velocity = (angle_adjusted - angle_adjusted_Old)*90.0;                  // 90 эмпирический коэффициент полученный при корректировке реальных показателей
    int16_t estimated_speed = -actual_robot_speed_Old - angular_velocity;                   // We use robot_speed(t-1) or (t-2) to compensate the delay
    estimated_speed_filtered = estimated_speed_filtered*0.95 + (float)estimated_speed*0.05;

      // SPEED CONTROL: This is a PI controller.
      // input: user throttle
      // variable: estimated robot speed
      // output: target robot angle to get the desired speed
    target_angle = speedPIControl(dt,estimated_speed_filtered,throttle,Kp_thr,Ki_thr);
    target_angle = constrain(target_angle,-max_target_angle,max_target_angle);                                   // limited output


      // Stability control: This is a PD controller.
      // input: robot target angle(from SPEED CONTROL)
      // variable: robot angle
      // output: Motor speed
      // Мы интегрируем реакцию (суммируя), так что на выходе имеем ускорение двигателя, а не его скорость вращения.
    control_output += stabilityPDControl(dt,angle_adjusted,target_angle,Kp,Kd);  

      // Вводим пользовательские корректировки по рулению в сигнал управления
    motor1 = control_output + steering;
    motor2 = control_output - steering;

    // Limit max speed (control output)
    motor1 = constrain(motor1,-MAX_CONTROL_OUTPUT,MAX_CONTROL_OUTPUT);  
    motor2 = constrain(motor2,-MAX_CONTROL_OUTPUT,MAX_CONTROL_OUTPUT);  
    te_SetMotorsSpeed(motor1, motor2);  
  }

  if(RequestBAT)
  {
    bat_level = analogRead(BATTERY_PIN)*K_bat;
    RequestBAT = false;
    if (page==1)
    {
      WiFi_MSG_Send_Float("/1/label1\0\0\0,f\0\0\0\0\0\0",20,bat_level);
      WiFi_MSG_Send_Float("/1/label2\0\0\0,f\0\0\0\0\0\0",20,dist_value);
    }
  }

  if (loop_counter > 400)
  {
    dist_value = echo_value * 0.0125 / 58; // в сантиметрах
    loop_counter = 0;
  }

}

В первом файле при инициализации выключаем моторы.
Во втором тоже их выключаем при углах наклона более 74 градусов и включаем при меньших углах.

Робот должен сам начать балансировать, если он находится в вертикальном положении.

Про OSCillation от iWork ничего сказать не могу, - не пользуюсь оной, равно как и автовозвратом ползунков в нейтральное положение.
Find all posts by this user
Quote this message in a reply
Post Reply 


Messages In This Thread
Only You, or ESP8266 Forever! - KomX - 05-07-2016, 05:50 PM
RE: Only You, or ESP8266 Forever! - KomX - 05-09-2016, 08:30 AM
RE: Only You, or ESP8266 Forever! - KomX - 05-09-2016, 03:54 PM
RE: Only You, or ESP8266 Forever! - KomX - 05-11-2016, 04:34 AM
RE: Only You, or ESP8266 Forever! - KomX - 05-12-2016, 04:35 AM
RE: Only You, or ESP8266 Forever! - KomX - 05-14-2016, 08:00 AM
RE: Only You, or ESP8266 Forever! - KomX - 05-15-2016 09:58 AM
RE: Only You, or ESP8266 Forever! - KomX - 05-15-2016, 04:46 PM
RE: Only You, or ESP8266 Forever! - KomX - 05-15-2016, 07:10 PM
RE: Only You, or ESP8266 Forever! - KomX - 05-15-2016, 08:38 PM
RE: Only You, or ESP8266 Forever! - KomX - 05-15-2016, 09:49 PM
RE: Only You, or ESP8266 Forever! - JohnQ - 05-16-2016, 10:14 AM
RE: Only You, or ESP8266 Forever! - KomX - 05-16-2016, 05:25 PM
RE: Only You, or ESP8266 Forever! - KomX - 05-16-2016, 09:33 PM
RE: Only You, or ESP8266 Forever! - KomX - 08-19-2016, 01:32 PM
RE: Only You, or ESP8266 Forever! - jimmy - 08-19-2016, 05:28 PM
RE: Only You, or ESP8266 Forever! - KomX - 08-19-2016, 10:20 PM
RE: Only You, or ESP8266 Forever! - jimmy - 08-19-2016, 10:29 PM
RE: Only You, or ESP8266 Forever! - KomX - 08-20-2016, 06:32 AM
RE: Only You, or ESP8266 Forever! - jimmy - 08-29-2016, 05:12 PM
RE: Only You, or ESP8266 Forever! - KomX - 09-09-2016, 09:05 AM
RE: Only You, or ESP8266 Forever! - rolfz - 12-06-2016, 04:42 PM
RE: Only You, or ESP8266 Forever! - KomX - 12-13-2016, 12:11 PM
RE: Only You, or ESP8266 Forever! - rolfz - 12-15-2016, 12:21 PM
RE: Only You, or ESP8266 Forever! - rolfz - 12-24-2016, 08:49 PM
RE: Only You, or ESP8266 Forever! - rolfz - 12-25-2016, 05:50 PM
RE: Only You, or ESP8266 Forever! - KomX - 12-26-2016, 10:27 AM
RE: Only You, or ESP8266 Forever! - KomX - 12-26-2016, 01:54 PM
RE: Only You, or ESP8266 Forever! - KomX - 12-26-2016, 06:40 PM
RE: Only You, or ESP8266 Forever! - KomX - 12-29-2016, 07:14 AM
RE: Only You, or ESP8266 Forever! - KomX - 12-30-2016, 04:42 AM
RE: Only You, or ESP8266 Forever! - KomX - 01-26-2017, 08:44 AM
RE: Only You, or ESP8266 Forever! - KomX - 01-30-2017, 07:14 AM
RE: Only You, or ESP8266 Forever! - KomX - 02-20-2017, 07:38 AM
RE: Only You, or ESP8266 Forever! - sirius - 04-13-2018, 11:19 AM

Forum Jump:


User(s) browsing this thread: 1 Guest(s)