ESP8266 - Trying to setup Twitch chat commands to trigger servo

Hi all,

Very much a noob - trying to adjust a code so that a servo is triggered when the command !feed is said in my Twitch chat. This is to create an automated pet feeder.

I’m using this as a template: https://github.com/noycebru/Twitch-chat-LED-lights/blob/main/main

The bot and StreamElements are working okay, but I’m not sure my servo coding is correct…

I have tested with a simple servo code and that works fine. Signal is connected to D1 / 05

  /*******************************************************************
    Connect to Twtich Chat with a Bot
   Created with code from TheOtherLoneStar (https://www.twitch.tv/theotherlonestar)
   Hackaday IO: https://hackaday.io/otherlonestar
   By Brian Lough (https://www.twitch.tv/brianlough)
   YouTube: https://www.youtube.com/channel/UCezJOfu7OtqGzd5xrP3q6WA
Created with code from noycebru www.twitch.tv/noycebru
 *******************************************************************/
 
#include <ESP8266WiFi.h>          //https://github.com/esp8266/Arduino
#include <IRCClient.h>
#include <Servo.h>

Servo servo; 

//define your default values here, if there are different values in config.json, they are overwritten.
#define secret_ssid "my ssid" 
#define IRC_SERVER   "irc.chat.twitch.tv"
#define IRC_PORT     6667
 
//------- Replace the following! ------
char ssid[] = "";       // your network SSID (name)
char password[] = "";  // your network key
 
//The name of the channel that you want the bot to join
const String twitchChannelName = ""; //this is case sensitive!
 
//The name that you want the bot to have
#define TWITCH_BOT_NAME ""
 
//OAuth Key for your twitch bot
// https://twitchapps.com/tmi/
#define TWITCH_OAUTH_TOKEN ""
 
 
//------------------------------
 

 
int feeder = 5;
String ircChannel = "";
 
WiFiClient wiFiClient;
IRCClient client(IRC_SERVER, IRC_PORT, wiFiClient);
 
// put your setup code here, to run once:
void setup() {
 
  pinMode(feeder, OUTPUT);
  servo.attach(5);
  servo.write(0);
  delay(2000);
  Serial.begin(115200);
  Serial.println();
 
  // Set WiFi to station mode and disconnect from an AP if it was Previously
  // connected
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
 
  // Attempt to connect to Wifi network:
  Serial.print("Connecting Wifi: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  IPAddress ip = WiFi.localIP();
  Serial.println(ip);
 
  ircChannel = "#" + twitchChannelName;
 
  client.setCallback(callback);
}
 
void loop() {
 
  // Try to connect to chat. If it loses connection try again
  if (!client.connected()) {
    Serial.println("Attempting to connect to " + ircChannel );
    // Attempt to connect
    // Second param is not needed by Twtich
    if (client.connect(TWITCH_BOT_NAME, "", TWITCH_OAUTH_TOKEN)) {
      client.sendRaw("JOIN " + ircChannel);
      Serial.println("connected and ready to rock");
      sendTwitchMessage("Ready to go Boss!");
    } else {
      Serial.println("failed... try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
    return;
  }
  client.loop();
}
 
void sendTwitchMessage(String message) {
  client.sendMessage(ircChannel, message);
}
 
 
void callback(IRCMessage ircMessage) {
  //Serial.println("In CallBack");
 
  if (ircMessage.command == "PRIVMSG" && ircMessage.text[0] != '\001') {
    //Serial.println("Passed private message.");
   
    ircMessage.nick.toUpperCase();
 
    String message("<" + ircMessage.nick + "> " + ircMessage.text);
 
    //prints chat to serial
    Serial.println(message);

//this is where you would replace these elements to match your streaming configureation. 
if (ircMessage.text.indexOf("subscribed") > -1 && ircMessage.nick == "STREAMELEMENTS")
      {
     
      pinMode(feeder, OUTPUT);
      servo.attach(5);
      servo.write(0);
      delay(2000);
      Serial.begin(115200);
      Serial.println();
   
    }

    if (ircMessage.text.indexOf("following") > -1 && ircMessage.nick == "STREAMELEMENTS")
      {
     
      pinMode(feeder, OUTPUT);
      servo.attach(5);
      servo.write(0);
      delay(2000);
      Serial.begin(115200);
      Serial.println();
   
    }

   if (ircMessage.text.indexOf("!feed") > -1 && ircMessage.nick == "STREAMELEMENTS")
      {
     
      pinMode(feeder, OUTPUT);
      servo.attach(5);
      servo.write(0);
      delay(2000);
      Serial.begin(115200);
      Serial.println();
   
    }

    if (ircMessage.text.indexOf("nuts!") > -1 && ircMessage.nick == "STREAMELEMENTS")
      {
     
      pinMode(feeder, OUTPUT);
      servo.attach(5);
      servo.write(0);
      delay(2000);
      Serial.begin(115200);
      Serial.println();
   
    }

    //servo control
if (ircMessage.text.indexOf("following") > -1 && ircMessage.nick == "STREAMELEMENTS")
{
     for (int i = 0; i <= 0; i++) {
            
      servo.write(180);
      delay(200);
        
   }
    for (int i = 1; i <= 3; i++) {
            
      servo.write(180);
      delay(500);
      servo.write(100);
      delay(200);
  } 
   for (int i = 3; i <= 3; i++) {
      
      servo.write(0);
      delay(500);
   } 
}

    for (int i = 1; i <= 3; i++) {
            
      servo.write(180);
      delay(500);
      servo.write(100);
      delay(200);
  } 
   for (int i = 3; i <= 3; i++) {
      
      servo.write(0);
      delay(500);
   } 
}
 
    return;
  }
}

You only need to attach() the servo once. Do it in setup()
The same goes for Serial.begin() and pinMode()

Some of the for loops controlling servo movement make no sense

A prime example, but there are others

      for (int i = 0; i <= 0; i++)
      {
        servo.write(180);
        delay(200);
      }

How many times will the for loop iterate ?

By the way, your code as posted does not compile. One too many } at the end of it

Thanks for replying, I’ve made some changes to the code based on your suggestions:

  /*******************************************************************
    Connect to Twtich Chat with a Bot
   Created with code from TheOtherLoneStar (https://www.twitch.tv/theotherlonestar)
   Hackaday IO: https://hackaday.io/otherlonestar
   By Brian Lough (https://www.twitch.tv/brianlough)
   YouTube: https://www.youtube.com/channel/UCezJOfu7OtqGzd5xrP3q6WA
Created with code from noycebru www.twitch.tv/noycebru
 *******************************************************************/
 
#include <ESP8266WiFi.h>          //https://github.com/esp8266/Arduino
#include <IRCClient.h>
#include <Servo.h>

Servo servo; 

//define your default values here, if there are different values in config.json, they are overwritten.
#define secret_ssid "my ssid" 
#define IRC_SERVER   "irc.chat.twitch.tv"
#define IRC_PORT     6667
 
//------- Replace the following! ------
char ssid[] = "";       // your network SSID (name)
char password[] = "";  // your network key
 
//The name of the channel that you want the bot to join
const String twitchChannelName = ""; //this is case sensitive!
 
//The name that you want the bot to have
#define TWITCH_BOT_NAME ""
 
//OAuth Key for your twitch bot
// https://twitchapps.com/tmi/
#define TWITCH_OAUTH_TOKEN ""
 
 
//------------------------------
 

 
int feeder = 5;
String ircChannel = "";
 
WiFiClient wiFiClient;
IRCClient client(IRC_SERVER, IRC_PORT, wiFiClient);
 
// put your setup code here, to run once:
void setup() {
 
  pinMode(feeder, OUTPUT);
  servo.attach(5);
  servo.write(0);
  delay(2000);
  Serial.begin(115200);
  Serial.println();
 
  // Set WiFi to station mode and disconnect from an AP if it was Previously
  // connected
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
 
  // Attempt to connect to Wifi network:
  Serial.print("Connecting Wifi: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  IPAddress ip = WiFi.localIP();
  Serial.println(ip);
 
  ircChannel = "#" + twitchChannelName;
 
  client.setCallback(callback);
}
 
void loop() {
 
  // Try to connect to chat. If it loses connection try again
  if (!client.connected()) {
    Serial.println("Attempting to connect to " + ircChannel );
    // Attempt to connect
    // Second param is not needed by Twtich
    if (client.connect(TWITCH_BOT_NAME, "", TWITCH_OAUTH_TOKEN)) {
      client.sendRaw("JOIN " + ircChannel);
      Serial.println("connected and ready to rock");
      sendTwitchMessage("Ready to go Boss!");
    } else {
      Serial.println("failed... try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
    return;
  }
  client.loop();
}
 
void sendTwitchMessage(String message) {
  client.sendMessage(ircChannel, message);
}
 
 
void callback(IRCMessage ircMessage) {
  //Serial.println("In CallBack");
 
  if (ircMessage.command == "PRIVMSG" && ircMessage.text[0] != '\001') {
    //Serial.println("Passed private message.");
   
    ircMessage.nick.toUpperCase();
 
    String message("<" + ircMessage.nick + "> " + ircMessage.text);
 
    //prints chat to serial
    Serial.println(message);

//this is where you would replace these elements to match your streaming configureation. 
if (ircMessage.text.indexOf("subscribed") > -1 && ircMessage.nick == "STREAMELEMENTS")
      {
     
      servo.write(0);
      delay(2000);
      Serial.println();
   
    }

    if (ircMessage.text.indexOf("following") > -1 && ircMessage.nick == "STREAMELEMENTS")
      {
     
      servo.write(0);
      delay(2000);
      Serial.println();
      
    }

   if (ircMessage.text.indexOf("!feed") > -1 && ircMessage.nick == "STREAMELEMENTS")
      {
     
      servo.write(0);
      delay(2000);
      Serial.println();
   
    }

    if (ircMessage.text.indexOf("nuts!") > -1 && ircMessage.nick == "STREAMELEMENTS")
      {
     
      servo.write(0);
      delay(2000);
      Serial.println();
   
    }

        if (ircMessage.text.indexOf("test") > -1 && ircMessage.nick == "myinvoluntarytwitch")
      {
     
      servo.write(0);
      delay(2000);
      Serial.println();
   
    }
    
    //servo control
if (ircMessage.text.indexOf("following") > -1 && ircMessage.nick == "STREAMELEMENTS")
{
     for (int i = 0; i <= 0; i++) {
            
      servo.write(180);
      delay(200);
        
   }
    for (int i = 1; i <= 3; i++) {
            
      servo.write(180);
      delay(500);
      servo.write(100);
      delay(200);
  } 
   for (int i = 3; i <= 3; i++) {
      
      servo.write(0);
      delay(500);
   } 
}

if (ircMessage.text.indexOf("test") > -1 && ircMessage.nick == "myinvoluntarytwitch")
{
     for (int i = 0; i <= 0; i++) {
            
      servo.write(180);
      delay(200);
        
   }
    for (int i = 1; i <= 3; i++) {
            
      servo.write(180);
      delay(500);
      servo.write(100);
      delay(200);
  } 
   for (int i = 3; i <= 3; i++) {
      
      servo.write(0);
      delay(500);
   } 
}
 
    return;
  }
}
     for (int i = 3; i <= 3; i++)
      {
        servo.write(0);
        delay(500);
      }
      for (int i = 0; i <= 0; i++)
      {
        servo.write(180);
        delay(200);
      }

I can’t believe that you are still using for loops like this

As before, how many times will the for loop iterate ?

Oops, forgot to get rid of those.

I just want the servo to move once. The for loops were left over from the original code.

Updated:

  /*******************************************************************
    Connect to Twtich Chat with a Bot
   Created with code from TheOtherLoneStar (https://www.twitch.tv/theotherlonestar)
   Hackaday IO: https://hackaday.io/otherlonestar
   By Brian Lough (https://www.twitch.tv/brianlough)
   YouTube: https://www.youtube.com/channel/UCezJOfu7OtqGzd5xrP3q6WA
Created with code from noycebru www.twitch.tv/noycebru
 *******************************************************************/
 
#include <ESP8266WiFi.h>          //https://github.com/esp8266/Arduino
#include <IRCClient.h>
#include <Servo.h>

Servo servo; 

//define your default values here, if there are different values in config.json, they are overwritten.
#define secret_ssid "my ssid" 
#define IRC_SERVER   "irc.chat.twitch.tv"
#define IRC_PORT     6667
 
//------- Replace the following! ------
char ssid[] = "";       // your network SSID (name)
char password[] = "";  // your network key
 
//The name of the channel that you want the bot to join
const String twitchChannelName = "myinvoluntarytwitch"; //this is case sensitive!
 
//The name that you want the bot to have
#define TWITCH_BOT_NAME "myinvoluntarytwitch"
 
//OAuth Key for your twitch bot
// https://twitchapps.com/tmi/
#define TWITCH_OAUTH_TOKEN ""
 
 
//------------------------------
 

 
int feeder = 5;
String ircChannel = "";
 
WiFiClient wiFiClient;
IRCClient client(IRC_SERVER, IRC_PORT, wiFiClient);
 
// put your setup code here, to run once:
void setup() {
 
  pinMode(feeder, OUTPUT);
  servo.attach(5);
  servo.write(0);
  delay(2000);
  Serial.begin(115200);
  Serial.println();
 
  // Set WiFi to station mode and disconnect from an AP if it was Previously
  // connected
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
 
  // Attempt to connect to Wifi network:
  Serial.print("Connecting Wifi: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  IPAddress ip = WiFi.localIP();
  Serial.println(ip);
 
  ircChannel = "#" + twitchChannelName;
 
  client.setCallback(callback);
}
 
void loop() {
 
  // Try to connect to chat. If it loses connection try again
  if (!client.connected()) {
    Serial.println("Attempting to connect to " + ircChannel );
    // Attempt to connect
    // Second param is not needed by Twtich
    if (client.connect(TWITCH_BOT_NAME, "", TWITCH_OAUTH_TOKEN)) {
      client.sendRaw("JOIN " + ircChannel);
      Serial.println("connected and ready to rock");
      sendTwitchMessage("Ready to go Boss!");
    } else {
      Serial.println("failed... try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
    return;
  }
  client.loop();
}
 
void sendTwitchMessage(String message) {
  client.sendMessage(ircChannel, message);
}
 
 
void callback(IRCMessage ircMessage) {
  //Serial.println("In CallBack");
 
  if (ircMessage.command == "PRIVMSG" && ircMessage.text[0] != '\001') {
    //Serial.println("Passed private message.");
   
    ircMessage.nick.toUpperCase();
 
    String message("<" + ircMessage.nick + "> " + ircMessage.text);
 
    //prints chat to serial
    Serial.println(message);

//this is where you would replace these elements to match your streaming configureation. 
if (ircMessage.text.indexOf("subscribed") > -1 && ircMessage.nick == "STREAMELEMENTS")
      {
     
      servo.write(150);
      delay(2000);
      Serial.println();
   
    }

    if (ircMessage.text.indexOf("following") > -1 && ircMessage.nick == "STREAMELEMENTS")
      {
     
      servo.write(150);
      delay(2000);
      Serial.println();
      
    }

   if (ircMessage.text.indexOf("!feed") > -1 && ircMessage.nick == "STREAMELEMENTS")
      {
     
      servo.write(150);
      delay(2000);
      Serial.println();
   
    }

    if (ircMessage.text.indexOf("nuts!") > -1 && ircMessage.nick == "StreamElements")
      {
     
      servo.write(150);
      delay(2000);
      Serial.println();
   
    }

        if (ircMessage.text.indexOf("test") > -1 && ircMessage.nick == "myinvoluntarytwitch")
      {
     
      servo.write(150);
      delay(2000);
      Serial.println();
   
    }
    
    //servo control
if (ircMessage.text.indexOf("following") > -1 && ircMessage.nick == "STREAMELEMENTS")
{
      servo.write(150);
      delay(2000);
      Serial.println();
        
   }
  }

 
    return;
  }

That looks a little better

What do you see if you print ircMessage.text on receipt of a message ?

Note that ircMessage.text[0] will never equal '\001' as far as I can see because single quotes are used around single characters

Sorry, how do I print ircMessage.text on receipt of a message?

I have just tested and the servo now moves when !feed is typed in the Twitch chat!

However, it only does this once until I disconnect and reconnect completely. Is there a way I can have the servo move an unlimited amount of times?

    if (ircMessage.text.indexOf("subscribed") > -1 && ircMessage.nick == "STREAMELEMENTS")
    {
      servo.write(150);
      delay(2000);
      Serial.println();
    }
    if (ircMessage.text.indexOf("following") > -1 && ircMessage.nick == "STREAMELEMENTS")
    {
      servo.write(150);
      delay(2000);
      Serial.println();
    }
    if (ircMessage.text.indexOf("!feed") > -1 && ircMessage.nick == "STREAMELEMENTS")
    {
      servo.write(150);
      delay(2000);
      Serial.println();
    }
    if (ircMessage.text.indexOf("nuts!") > -1 && ircMessage.nick == "StreamElements")
    {
      servo.write(150);
      delay(2000);
      Serial.println();
    }
    if (ircMessage.text.indexOf("test") > -1 && ircMessage.nick == "myinvoluntarytwitch")
    {
      servo.write(150);
      delay(2000);
      Serial.println();
    }
    //servo control
    if (ircMessage.text.indexOf("following") > -1 && ircMessage.nick == "STREAMELEMENTS")
    {
      servo.write(150);
      delay(2000);
      Serial.println();
    }

Whenever a match is found to any command your code moves the servo to 150 so it stays there once it has moved. Change one or more of the values in servo.write() for other commands and try them

Ah I see, that makes sense.

If I wanted to set a 'default' servo.write for the servo to start on, is there an appropriate place to put that?

I've tried a few places but it's causing errors.

EDIT:

Actually, if I add a servo.write(0) after the delay, that should get me back to the 'default' position right?

If I wanted to set a 'default' servo.write for the servo to start on, is there an appropriate place to put that?

  servo.write(0);

The servo start position is right here in setup()

Right, I see - thank you!

This is absolutely amazing, it's working! I need to adjust the delay so it's not as slow...

I have an SG90 servo - it's vibrating constantly. Are there servos that don't vibrate? Is it healthy for it to be vibrating if I have it running for a long time?

You could use servo.detach() after moving the servo but the output arm will then be free to move if a load is applied to it. What is it driving ?

Okay thanks, I'll try that. It'll have a small piece of plastic attached to it that will move horizontally to release the food with gravity.

Similar to this:

servo.detach() is working perfectly. This is exactly what I need, thanks for your patience and help.
Updated code:

    if (ircMessage.text.indexOf("nuts!") > -1 && ircMessage.nick == "STREAMELEMENTS")
      {

      servo.attach(5);
      servo.write(180);
      delay(750);
      servo.write(0);
      delay(1000);
      servo.detach();
     
    }

I am glad that it is working and I can only assume that you are satisfied with the fact that the action can only occur once

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.