Hi!
I want to create an IRC bot with my arduino and an ethernet shield. Its working fine for the first time i start it. If i reset the arduino via Software, hardware button/ureplug the irc bot joins the channel, can send messages bot does not receive messages. or with a huge delay which will end in a timeout after a few seconds. Or it doesnt display any message from the channel.
At the moment it seems that plugging the arduino off for ~15minutes helps to get the bot running again. But thats driving me crazy for debugging.
Maybe someone knows a common thing i am doing wrong? Or even better: Maybe someone can test the sketch on his own to see if its a hardware problem of my shield/network.
Here is my sketch:
/*
http://www.hcidata.info/host2ip.htm
*/
#include <SPI.h>
#include <Ethernet.h>
#define W5200_SS 10
#define SDCARD_SS 4
const int pinLed = 13;
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 178, 100);
byte gateway[] = {
192, 168, 178, 1 };
byte subnet[] = {
255,255,255,0 };
// Enter the IP address of the ircServer you're connecting to:
//IPAddress ircServer(38, 229, 70, 20); // freenode
IPAddress ircServer(62,231,75,133); // freenode #2
//IPAddress ircServer(85, 25, 243, 156); // irc-mania.de
//IPAddress ircServer(130,133,8,2); // irc.fu-berlin.de
bool handleIRC(void);
String ircUser = "HoodBot";
String ircNick = "HoodBot";
String ircChannel = "#bottest";
// Initialize the Ethernet client library
// with the IP address and port of the ircServer
// that you want to connect to (port 23 is default for telnet;
// if you're using Processing's ChatircServer, use port 10002):
EthernetClient client;
int port = 6667;
// prints text to Serial and Client
void bothprint(String text) {
Serial.print(text);
client.print(text);
}
void bothprintln(String text) {
Serial.println(text);
client.println(text);
}
void setup() {
// start the serial debug
Serial.begin(115200);
// Led setup
pinMode(pinLed, OUTPUT);
//Deselect the SD card
pinMode(SDCARD_SS, OUTPUT);
digitalWrite(SDCARD_SS, HIGH);
// attempt a DHCP connection:
Serial.println("Attempting to get an IP address using DHCP:");
//Ethernet.begin(mac, ip, subnet, gateway);
if (!Ethernet.begin(mac)) {
// if DHCP fails, start with a hard-coded address:
Serial.println("failed to get an IP address using DHCP, trying manually");
Ethernet.begin(mac, ip);
}
Serial.print("My address: ");
Serial.println(Ethernet.localIP());
Serial.println("===Setup done===");
delay(1000);
}
bool readClient(void) {
static unsigned long prevClientMessage = 0;
static bool newClientMessage = false;
// reads all bytes from the client and print them to the serial
if (uint16_t(client.available())) {
Serial.println(uint16_t(client.available()), HEX);
while (uint16_t(client.available())) {
char c = client.read();
Serial.write(c);
// keep connection alive with PONG, very simple
static char ping[4];
static uint8_t pinglen = 0;
if ( pinglen == 0 && c == 'P'
|| pinglen == 1 && c == 'I'
|| pinglen == 2 && c == 'N'
|| pinglen == 3 && c == 'G')
pinglen++;
else pinglen = 0;
if (pinglen == 4) {
Serial.println(); // just that it not look soo weird in the debug screen
bothprint("PONG :msg\r\n");
pinglen = 0;
}
}
prevClientMessage == millis();
newClientMessage = true;
}
if (newClientMessage) {
// wait for timeout
if (millis() - prevClientMessage > 1000) {
newClientMessage = false;
Serial.println("====================");
return false;
}
else
return true;
}
// nothing new to read
else
return false;
}
void loop()
{
if (!client.connected()) {
Serial.println("Connecting ...");
if (client.connect(ircServer, port)) {
while (readClient());
Serial.println("Connected! Joining channel...");
while (readClient());
delay(3000);
bothprint("USER uk 8 * : ");
bothprint(ircUser);
bothprint("\r\n");
bothprint("NICK ");
bothprint(ircNick);
bothprint("\r\n");
while (readClient());
delay(1000);
while (readClient());
delay(3000);
bothprint("JOIN ");
bothprint(ircChannel);
bothprint("\r\n");
while (readClient());
delay(3000);
Serial.println("===Channel joined!===");
bothprint("PRIVMSG ");
bothprint(ircChannel);
bothprint(" :Hello World!");
bothprint("\r\n");
// handle signal until timeout
while (handleIRC()){
digitalWrite(pinLed, HIGH);
delay(100);
digitalWrite(pinLed, LOW);
delay(100);
}
}
else {
// if you didn't get a connection to the ircServer:
Serial.println("Connection failed");
Serial.println("Reconnecting in 15 seconds");
delay(15000);
// reconnect doesnt work at the moment.
// TODO <--
}
}
}
bool handleIRC(void) {
// abort if host disconnected
if (!client.connected()) {
Serial.println("Disconnected");
return false;
}
// read all bytes from the client and print it to the serial
while (readClient());
if (Serial.available()) {
// if serial message start with "!" it will send a raw command
if (Serial.peek() == '!') {
// discard this '!' byte
Serial.read();
// give the serial time to receive data
delay(100);
// print all bytes as raw but add the \r\n
// print all data to the serial and client
while (Serial.available()) {
char c = Serial.read();
Serial.write(c);
client.write(c);
}
bothprint("\r\n");
return true;
}
Serial.println("Printing to IRC:");
bothprint("PRIVMSG ");
bothprint(ircChannel);
bothprint(" :");
// give the Serial time to receive all data (limited to 64 bytes at the moment)
delay(100);
// print all data to the serial and client
while (Serial.available()) {
char c = Serial.read();
Serial.write(c);
client.write(c);
}
bothprint("\r\n");
}
return true;
}
What you should know about the sketch: Set baud to 115200, no line encoding. You can chat with the serial and it will keep conection with a pong automatic. just enter a freenode channel to join. You can use this testchannel. Connect via pc and try to send messages. The arduino should display everything. Try to write a few messages and see if it keeps connecting. after the reset it shouldnt work for about 15 minutes if you unplug it. If it has a proper run you can spam as much as you want and the arduino will keep connected and display all messages, maybe with some delay.
edit: you can now use a ! to type in raw commands like
!PING 85.25.243.156
I need to notice that i am using the elecrow w5200 shield. I tried all existing 4 libraries. Maybe its a problem of the shield. The sketch should work with a w5100 too.
What i also tried: Used no usb hub (had problems with not enough VCC).
Tried a laptop
Tried to connect it direct to my router (fritzbox)
tried different libraries for w5200.
Edit: I had to use client.stop() to shut the shield down properly. Otherwise you get weird errors.!