Electric TV Stand(Alexa-enabled)

by asatomomoka in Workshop > Furniture

312 Views, 1 Favorites, 0 Comments

Electric TV Stand(Alexa-enabled)

サイバーテレビダイ

This is a TV stand that turns around when you call out to Alexa!

You will be able to see the TV better from where you are sitting!

Alexa commands the microcontroller to turn the servo and move the TV stand.


How about a useful piece of furniture, not just a piece of furniture?

Supplies

* TV stand

* A board the same size as the TV stand

* Bearings

* Servo

* Gears (3D printed)

* Limit switch x 2

* M5 ATOM S3

* Alexa

Carpenters

IMG_20241022_223448.jpg

1. cut out a board the same size as the TV stand

2. make a top board with a bearing on top of the TV stand

Driving Force

a69814db-d97c-46c4-855d-c1e31d2c5e63.png
IMG_20250211_173528.jpg

3.Mount the printed gear on it.

4. attach the gear to the servo so that it can be driven.

Downloads

Circuit

sen.png

5.Connect the circuit as shown in the figure.

6.Drive the servo with M5 ATOM S3.

7.Assign an action to the device so that Alexa will recognize it as a device.

Facilitate

I'm sitting at the living room table and I can't see the TV well from where I'm sitting.

The TV is on, but you can't keep up with what's being discussed ...

For this reason, we have created a system that allows you to change the direction of the TV by simply commanding Alexa to change the direction of the TV.

It is convenient to be able to change the direction by voice


Code

Stops when it rotates and the limit switch turns ON

There is a safety function that automatically stops the machine after a certain period of time without rotation.

LED tape can be attached to light up as it rotates.

Specify 50% brightness to Alexa



#include "M5AtomS3.h" // ATOM S3 用ライブラリ

#ifdef ARDUINO_ARCH_ESP32
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
#endif
#include <Espalexa.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
#include "ESP32Servo.h"

#define PIN G39 // On Trinket or Gemma, suggest changing this to 1
#define NUMPIXELS 16 // Popular NeoPixel ring size

Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

//G8 poWER
//サーボ G6 リミット前G7 後ろ?G5
const int SERVO_CENTER = 1310; //サーボの中心値
Servo myservo;
void Servo_move(int servo_speed);
int move;
int moveOld = 1;

//G5 LED7
//G6 mi
//G7 BEEP
//G8 poWER
//G38 39 G1 G2

#define SW (3)
int step_number = 0;
void OneStep(bool dir);

// prototypes
boolean connectWifi();

void secondLightChanged(uint8_t brightness);
void thirdLightChanged(uint8_t brightness);

void Stop();

// Change this!!
const char* ssid = "XXXX";
const char* password = "xxxxx";

boolean wifiConnected = false;
int anmCount;

Espalexa espalexa;

float v = 0.0f;
bool mizuFlag;
bool ampFlag;
int count;
uint8_t mizuBrightness;
unsigned long killTimer;
float ledMove;


EspalexaDevice* device3;

void setup()
{
Serial.begin(115200);
M5.begin(); // M5Stack用ライブラリの起動
M5.Lcd.fillScreen(BLACK); // LCDを消去
M5.Lcd.setRotation(0); // LCDを縦向き表示に設定
M5.Lcd.println("Example 0 M5 ATOM S3"); // LCDにタイトルを表示

killTimer = millis();

if (!myservo.attached()) {
myservo.setPeriodHertz(50); // standard 50 hz servo
myservo.attach(G6, 1000, 2000); // Attach the servo after it has been detatched
}
Servo_move(100);
delay(250);
Servo_move(0);
delay(25);
Servo_move(-100);
delay(250);
Servo_move(0);
delay(25);
myservo.detach();

pinMode(G8, OUTPUT);//poWER

pinMode(G7, INPUT_PULLUP);//リミット
pinMode(G5, INPUT_PULLUP);//リミット

pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
pixels.clear(); // Set all pixel colors to 'off'
pixels.setPixelColor(0, pixels.Color(255, 255, 255));
pixels.show(); // Send the updated pixel colors to the hardware.
delay(50); // Pause before next pass through loop
pixels.clear(); // Set all pixel colors to 'off'
pixels.show(); // Send the updated pixel colors to the hardware.

// Initialise wifi connection
wifiConnected = connectWifi();

if(wifiConnected){
espalexa.addDevice("Tv", thirdLightChanged); //third parameter is beginning state (here fully on)
espalexa.begin();

} else
{
while (1) {
Serial.println("Cannot connect to WiFi. Please check data and reset the ESP.");
delay(2500);
}
}
}


void loop()
{
int r, g, b;
r = 1;
g = 0;
b = 0;

espalexa.loop();
delay(1);

if(move != 0){
ledMove -= move * 0.1;
if(ledMove < 0) ledMove = NUMPIXELS -1;
if(ledMove > NUMPIXELS -0.1) ledMove = 0;
pixels.clear(); // Set all pixel colors to 'off'
pixels.setPixelColor(ledMove, pixels.Color(55, 20, 255));
pixels.show(); // Send the updated pixel colors to the hardware.
}

//正転停止
if(move == -1 && (!digitalRead(G7) || killTimer < millis())){
Stop();
}
//逆転停止
if(move == 1 && (!digitalRead(G5) || killTimer < millis())){
Stop();
}

if(mizuFlag){
if(mizuBrightness == 2550){//未使用
pixels.clear(); // Set all pixel colors to 'off'
for(int i=0; i<NUMPIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(255, 255, 255));
}
pixels.show(); // Send the updated pixel colors to the hardware.
}
else{

anmCount++;
if(anmCount >= mizuBrightness){
anmCount = mizuBrightness;
}
else{
pixels.clear(); // Set all pixel colors to 'off'

for(int i=0; i<NUMPIXELS; i++) {
b = anmCount/12;
if(b > 20){
b = 20;
}
g = anmCount/2.5;
if(g > 90) g = 90;
r = anmCount;
pixels.setPixelColor(i, pixels.Color(r, g, b));
}
delay(5); // Pause before next pass through loop
pixels.show(); // Send the updated pixel colors to the hardware.
}
}
}
}

void Stop()
{
move = 0;
Servo_move(0);
delay(250);
myservo.detach();
M5.Lcd.fillScreen(BLACK); // LCDを消去
M5.Lcd.setBrightness(30);
delay(250);
for(int i=0; i<NUMPIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(100, 55, 255));
}
pixels.show(); // Send the updated pixel colors to the hardware.

delay(250);
pixels.clear(); // Set all pixel colors to 'off'
pixels.show(); // Send the updated pixel colors to the hardware.
}

//アンプ
void firstLightChanged(uint8_t brightness) {
Serial.print("Device 1 changed to ");

M5.Lcd.setTextSize(4);
if (!ampFlag) {
M5.Lcd.println("ON AMP");
M5.Lcd.println(brightness);
digitalWrite(G8, HIGH);
ampFlag = true;
}
else {
M5.Lcd.println("OFF AMP");
digitalWrite(G8, LOW);
ampFlag = false;
}
}

//Tv台
void thirdLightChanged(uint8_t brightness) {//fourthLightChanged
AtomS3.Lcd.setCursor(2, 2); // Set the cursor at (2,2). 将光标设置在(2,2)处
M5.Lcd.setBrightness(200);
M5.Lcd.fillScreen(BLACK); // LCDを消去

M5.Lcd.println(brightness);

M5.Lcd.setTextSize(4);
//アンプ操作
if(brightness == 0 || brightness == 255){
firstLightChanged(brightness);
return;
}
//ランプ
if(brightness > 128){
secondLightChanged(brightness);
return;
}

Serial.print("Device 1 changed to ");

myservo.attach(G6, 1000, 2000); // Attach the servo after it has been detatched
move = -moveOld;
moveOld = move;
Servo_move(move*100);
M5.Lcd.setTextSize(10);
M5.Lcd.setCursor(2, 2);
if(move < 0){
M5.Lcd.println(">>");
}
else{
M5.Lcd.println("<<");
}
M5.Lcd.setTextSize(2);
killTimer = millis() +60*1000;
delay(25);
}

//LEDランプ
void secondLightChanged(uint8_t brightness) {
if (!mizuFlag) {
anmCount = 0;
M5.Lcd.println("ON LED");
mizuFlag = true;
mizuBrightness = 250;//brightness;
}
else {
pixels.clear(); // Set all pixel colors to 'off'
pixels.show(); // Send the updated pixel colors to the hardware.
M5.Lcd.println("OFF LED");
mizuFlag = false;
}
}

boolean connectWifi()
{
bool done = true;
WiFi.begin(ssid, password);
while (done) {
M5.Lcd.println("WiFi connecting");
auto last = millis();
while (WiFi.status() != WL_CONNECTED && last + 5000 > millis()) {
delay(500);
M5.Lcd.print(".");
}
if (WiFi.status() == WL_CONNECTED) {
done = false;
} else {
M5.Lcd.println("retry");
WiFi.disconnect();
WiFi.reconnect();
}
}
M5.Lcd.println("\nWiFi connected.");
return true;
}

//サーボ動作
void Servo_move(int servo_speed)
{
myservo.writeMicroseconds(SERVO_CENTER+servo_speed);
}