Can't Establish Communication - CC3000 + Arduino Uno || TCP/UDP via C#

Hi all,

I am trying to write an Arduino sketch (that will be uploaded to an Arduino Uno combined with a CC3000 wireless module by Sparkfun).
This sketch should connect to a server PC, and send information via TCP/IP in the form of "1" or "0".

The problem is that the Server program (run separately on a PC with an IP of 192.168.2.13 [not static]),
does not seem to identify that the CC3000 (the client), is trying to establish a connection.

The current Arduino sketch (Client) is as below.
Of course I changed the "SSID" and "PASSWORD" with the actual SSID and PASSWORD... The CC3000 initializes and connects to the local WiFi with no problem.

Client Code (Arduino UNO + CC3000 WiFi Side):

//////////////// WIFI INITIALIZATION //////////////////
/****************************************************************/
#include <SPI.h>
#include <SFE_CC3000.h>
#include <SFE_CC3000_Client.h>

// Pins
#define CC3000_INT      2   // Needs to be an interrupt pin (D2/D3)
#define CC3000_EN       7   // Can be any digital pin
#define CC3000_CS       10  // Preferred is pin 10 on Uno

// Connection info data lengths
#define IP_ADDR_LEN     4   // Length of IP address in bytes

// Constants
char ap_ssid[] = "SSID";            // SSID of network
char ap_password[] = "PASSWORD";          // Password of network
unsigned int ap_security = WLAN_SEC_WPA2; // Security of network
// ap_security can be any of: WLAN_SEC_UNSEC, WLAN_SEC_WEP, 
// WLAN_SEC_WPA, or WLAN_SEC_WPA2
unsigned int timeout = 10000;          // Milliseconds
char server[] = "192.168.2.13";        // Remote server 

// Global Variables
SFE_CC3000 wifi = SFE_CC3000(CC3000_INT, CC3000_EN, CC3000_CS);
SFE_CC3000_Client client = SFE_CC3000_Client(wifi);
int ConnectionIndicator;

/****************************************************************/
//////////////// LDR INITIALIZATION //////////////////
/****************************************************************/
int LDR = 0;     //analog pin to which LDR is connected, here we set it to 0 so it means A0
int LDRValue = 0;      //that’s a variable to store LDR values
int light_sensitivity = 500;    //This is the approx value of light surrounding your LDR
boolean Toilet_Stat;
/****************************************************************/



void setup()
{
//////////////// WIFI SETUP //////////////////  
/****************************************************************/

	ConnectionInfo connection_info;
	int i;

	// Initialize Serial port
	Serial.begin(115200);
	Serial.println();
	Serial.println("---------------------------");
	Serial.println("SparkFun CC3000 - WebClient");
	Serial.println("---------------------------");

	// Initialize CC3000 (configure SPI communications)
	if (wifi.init())
	{
		Serial.println("CC3000 initialization complete");
	}

	else
	{
		Serial.println("Something went wrong during CC3000 init!");
	}

	// Connect using DHCP
	Serial.print("Connecting to SSID: ");
	Serial.println(ap_ssid);
	if (!wifi.connect(ap_ssid, ap_security, ap_password, timeout))
	{
		Serial.println("Error: Could not connect to AP");
	}

	// Gather connection details and print IP address
	if (!wifi.getConnectionInfo(connection_info))
	{
		Serial.println("Error: Could not obtain connection details");
	}

	else
	{
		Serial.print("IP Address: ");
		for (i = 0; i < IP_ADDR_LEN; i++)
		{
			Serial.print(connection_info.ip_address[i]);
			if (i < IP_ADDR_LEN - 1)
			{
				Serial.print(".");
			}
		}
		Serial.println();
	}

	// Make a TCP connection to remote host
	Serial.print("Connecting with Server: ");
	Serial.println(server);

	ConnectionIndicator = client.connect(server, 80);
	Serial.println(ConnectionIndicator); //Returns an int (1, -1, -2, -3, -4) indicating connection status:
	//SUCCESS (1)
	//TIMED_OUT (-1)
	//INVALID_SERVER (-2)
	//TRUNCATED  (-3)
	//INVALID_RESPONSE (-4)
	
	if (ConnectionIndicator==1)
	{
		Serial.println("Success: TCP connection Established!");
	}
	else if (ConnectionIndicator <= -1)
	{
		Serial.println("Error: Could not make a TCP connection");
	}

	/****************************************************************/
	//////////////// LDR SETUP //////////////////  
	/****************************************************************/
	
			
		pinMode(13, OUTPUT);   //Use 13 because there is already a built in yellow LED in Arduino which shows output when pin 13 is enabled.
	
}


void loop()
{
	LDRValue = analogRead(LDR);//reads the ldr’s value through LDR 

	if (LDRValue>500)
	{
		Toilet_Stat = 0;
		Serial.println(LDRValue);//prints the LDR values to serial monitor
		Serial.println(Toilet_Stat);
		client.write(Toilet_Stat);
	}
	else
	{
		Toilet_Stat = 1;
		Serial.println(LDRValue);//prints the LDR values to serial monitor
		Serial.println(Toilet_Stat);
		client.write(Toilet_Stat);
	}

	if (LDRValue > light_sensitivity)
	{
		digitalWrite(13, LOW);
	}
	else
	{
		digitalWrite(13, HIGH);
	}
	delay(1000); 
	//This is the speed by which LDR sends value to arduino   
	/****************************************************************/
}

Server Code (Computer Side):
Written in C#

//
/*   Server Program    */

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;

public class serv
{
    public static void Main()
    {
        try
        {
            IPAddress ipAd = IPAddress.Parse("192.168.2.13");
            // use local m/c IP address, and 
            // use the same in the client

            /* Initializes the Listener */
            TcpListener myList = new TcpListener(ipAd, 80);

            /* Start Listeneting at the specified port */
            myList.Start();

            Console.WriteLine("The server is running at port 80...");
            Console.WriteLine("The local End point is  :" +
                              myList.LocalEndpoint);
            Console.WriteLine("Waiting for a connection.....");

            Socket s = myList.AcceptSocket();
            Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);

            byte[] b = new byte[100];
            int k = s.Receive(b);
            Console.WriteLine("Recieved...");
            for (int i = 0; i < k; i++)
                Console.Write(Convert.ToChar(b[i]));

            ASCIIEncoding asen = new ASCIIEncoding();
            s.Send(asen.GetBytes("The string was recieved by the server."));
            Console.WriteLine("\nSent Acknowledgement");
            /* clean up */
            s.Close();
            myList.Stop();

        }
        catch (Exception e)
        {
            Console.WriteLine("Error..... " + e.StackTrace);
        }
    }

}

I guess the problematic section with the Arduino code, is this:
I can't seem to understand what is wrong with it, maybe there is something missing...

	// Make a TCP connection to remote host (server computer)
	Serial.print("Connecting to Server: ");
	Serial.println(server);

	ConnectionIndicator = client.connect(server, 80);
	Serial.println(ConnectionIndicator); // "client.connect" function returns an int (1, -1, -2, -3, -4) indicating connection status:
	//SUCCESS (1)
	//TIMED_OUT (-1)
	//INVALID_SERVER (-2)
	//TRUNCATED  (-3)
	//INVALID_RESPONSE (-4)
	
	if (ConnectionIndicator==1)
	{
		Serial.println("Success: TCP connection Established!");
	}
	else if (ConnectionIndicator <= -1)
	{
		Serial.println("Error: Could not make a TCP connection");
	}

This code line:

client.connect(server, 80);

Doesn't seem to return one of the values (1, -1, -2, -3, -4)
instead it always returns "0"
which is not even in the options for this function as I understand...

By the way, the C# code (Server part) was taken from here:

The server+client code written in this page seems to work perfectly together.

I am puzzled...

Help would be appreciated a lot!

Thanks in Advance.

It could be usefull to see the output of the C#.

Ramirez7:
The CC3000 initializes and connects to the local WiFi with no problem.

So the problem is the communication, not the hardware.
(silently assuming that the PC is reachable via WiFi at all)

The TCP port you are using (80), is the standard HTTP port,
so any 'webserver' on the PC would hinder you to use the port for your application,
so one of the following could just fail.

/* Initializes the Listener */
TcpListener myList = new TcpListener(ipAd, 80);

 /* Start Listeneting at the specified port */
myList.Start();

Which brings us back to line 1: It could be usefull to see the output of the C#.

There are quite a couple of things that can go wrong in a simple request/response transaktion, I try to summarize:

  • request could not be sent (ruled out)
  • request does not reach the target
  • target can not receive
  • target can not answer
  • response does not reach the client
  • client can not receive (ruled out)
    Running WireShark on your PC will show you at least where you have to look.

Whandall:
It could be usefull to see the output of the C#.

Please see attached picture file "C# Server.jpg".

Whandall:
So the problem is the communication, not the hardware.
(silently assuming that the PC is reachable via WiFi at all)

The PC is connected to the internet through an Ethernet cable.
It has internet access, and its own IP

Isn't that good enough in order to accept an incoming connection from the
Arduino+CC3000 WiFi module, which has its own IP (different from the PC IP of course)?

Whandall:
The TCP port you are using (80), is the standard HTTP port,
so any 'webserver' on the PC would hinder you to use the port for your application,
so one of the following could just fail.

I also attached the IPCONFIG of the PC.
Also, changed the server port to 2000 (random choice) and
of course, the problem still exists.

Does this help you or anyone else to understand the problem better and help me with this?
If not, just tell me what info you need and I will try to provide it.

Thanks a lot!

IP Config.jpg

So it seems the TCP port could be opened on the PC
(you did not show the port 80 result which you code uses, you changed the ports on both sides, didn't you?)
I can see nothing suspicious in the IP config of the PC,
but I fail in finding the settings of the CC300.

Ramirez7:
The PC is connected to the internet through an Ethernet cable. It has internet access, and its own IP.

That does not qualify as 'reachable via WiFi'.
Did you ever successfully communicate with a WiFi device and your PC?
(A ping from/to your smartphone?)

There are many possibilities to (mis)configure a LAN+WLAN combination.
How did you setup yours, which router/access point do you use?

Running WireShark on your PC will show you all packets that enter or leave the PC.
The benefit in narrowing the error domain should be obvious.

You could ping the CC300 from the PC and see a working UDP transaction
(I never used any Arduino WiFi stuff, but that should by all means work).

And before I forget: run WireShark (or similar).

Whandall:
So it seems the TCP port could be opened on the PC
(you did not show the port 80 result which you code uses, you changed the ports on both sides, didn't you?)

Yes. I changed the port also in the Arduino sketch I am using in order to config the CC3000 to communicate with my PC. They both have port 2000 now.

The Arduino code with port 2000 is here:

//////////////// WIFI INITIALIZATION //////////////////
/****************************************************************/
#include <SPI.h>
#include <SFE_CC3000.h>
#include <SFE_CC3000_Client.h>

// Pins
#define CC3000_INT      2   // Needs to be an interrupt pin (D2/D3)
#define CC3000_EN       7   // Can be any digital pin
#define CC3000_CS       10  // Preferred is pin 10 on Uno

// Connection info data lengths
#define IP_ADDR_LEN     4   // Length of IP address in bytes

// Constants
char ap_ssid[] = "SSID";            // SSID of network
char ap_password[] = "PASSWORD";          // Password of network
unsigned int ap_security = WLAN_SEC_WPA2; // Security of network
// ap_security can be any of: WLAN_SEC_UNSEC, WLAN_SEC_WEP, 
// WLAN_SEC_WPA, or WLAN_SEC_WPA2
unsigned int timeout = 10000;          // Milliseconds
char server[] = /*"www.google.com";*/ "192.168.2.13";        // Remote host site

// Global Variables
SFE_CC3000 wifi = SFE_CC3000(CC3000_INT, CC3000_EN, CC3000_CS);
SFE_CC3000_Client client = SFE_CC3000_Client(wifi);
int ConnectionIndicator;

/****************************************************************/
//////////////// LDR INITIALIZATION //////////////////
/****************************************************************/
int LDR = 0;     //analog pin to which LDR is connected, here we set it to 0 so it means A0
int LDRValue = 0;      //that’s a variable to store LDR values
int light_sensitivity = 500;    //This is the approx value of light surrounding your LDR
boolean Toilet_Stat;
/****************************************************************/



void setup()
{
//////////////// WIFI SETUP //////////////////  
/****************************************************************/

	ConnectionInfo connection_info;
	int i;

	// Initialize Serial port
	Serial.begin(115200);
	Serial.println();
	Serial.println("---------------------------");
	Serial.println("SparkFun CC3000 - WebClient");
	Serial.println("---------------------------");

	// Initialize CC3000 (configure SPI communications)
	if (wifi.init())
	{
		Serial.println("CC3000 initialization complete");
	}

	else
	{
		Serial.println("Something went wrong during CC3000 init!");
	}

	// Connect using DHCP
	Serial.print("Connecting to SSID: ");
	Serial.println(ap_ssid);
	if (!wifi.connect(ap_ssid, ap_security, ap_password, timeout))
	{
		Serial.println("Error: Could not connect to AP");
	}

	// Gather connection details and print IP address
	if (!wifi.getConnectionInfo(connection_info))
	{
		Serial.println("Error: Could not obtain connection details");
	}

	else
	{
		Serial.print("IP Address: ");
		for (i = 0; i < IP_ADDR_LEN; i++)
		{
			Serial.print(connection_info.ip_address[i]);
			if (i < IP_ADDR_LEN - 1)
			{
				Serial.print(".");
			}
		}
		Serial.println();
	}

	// Make a TCP connection to remote host
	Serial.print("Connecting with Server: ");
	Serial.println(server);

	ConnectionIndicator = client.connect(server, 2000);
	Serial.println(ConnectionIndicator); //Returns an int (1, -1, -2, -3, -4) indicating connection status:
	//SUCCESS (1)
	//TIMED_OUT (-1)
	//INVALID_SERVER (-2)
	//TRUNCATED  (-3)
	//INVALID_RESPONSE (-4)
	
	if (ConnectionIndicator==1)
	{
		Serial.println("Success: TCP connection Established!");
	}
	else if (ConnectionIndicator <= -1)
	{
		Serial.println("Error: Could not make a TCP connection");
	}

	/****************************************************************/
	//////////////// LDR SETUP //////////////////  
	/****************************************************************/
	
	
		/*Serial.begin(115200);  //start the serial monitor with 115200 buad*/
		pinMode(13, OUTPUT);   //we mostly use 13 because there is already a built in yellow LED in arduino which shows output when 13 pin is enabled
	
}


void loop()
{
	LDRValue = analogRead(LDR);//reads the ldr’s value through LDR 

	if (LDRValue>500)
	{
		Toilet_Stat = 0;
		Serial.println(LDRValue);//prints the LDR values to serial monitor
		Serial.println(Toilet_Stat);
		client.write(Toilet_Stat);
	}
	else
	{
		Toilet_Stat = 1;
		Serial.println(LDRValue);//prints the LDR values to serial monitor
		Serial.println(Toilet_Stat);
		client.write(Toilet_Stat);
	}

	if (LDRValue > light_sensitivity)
	{
		digitalWrite(13, LOW);
	}
	else
	{
		digitalWrite(13, HIGH);
	}
	delay(1000); 
	//This is the speed by which LDR sends value to arduino   
	/****************************************************************/
}

Whandall:
That does not qualify as 'reachable via WiFi'.
Did you ever successfully communicate with a WiFi device and your PC?
(A ping from/to your smartphone?)

Please have a look at the attached picture: "Smartphone PING from PC.jpg"
I pinged my smartphone from my PC.
It seems OK to me. Am I wrong?

Whandall:
There are many possibilities to (mis)configure a LAN+WLAN combination.
How did you setup yours, which router/access point do you use?

I am a Mechanical engineer with little knowledge about network. Sorry, but I'm not sure what to answer to this. I am doing this project at work, so my PC is connected to a local network, and of course the internet. We also have WiFi here, to which the CC3000 is connected.

I thought that after connecting both devices (PC and CC3000) to the internet, they would be able to communicate. Am I wrong?
Should I be trying to use the LAN+WLAN instead of using the internet, in order to transfer the data between the devices?

Whandall:
Running WireShark on your PC will show you all packets that enter or leave the PC.
The benefit in narrowing the error domain should be obvious.

I downloaded WireShark and ran it. While it was running I ran also the CC3000 (Client) and the C# (server) program.
I tried to see if I could get on something, but couldn't figure out where I should look and what exactly I should look for. There is a lot of information, and it would probably help to narrow down what I'm looking at (I assume I need to look at a very specific place in WireShark...)

Whandall:
You could ping the CC300 from the PC and see a working UDP transaction
(I never used any Arduino WiFi stuff, but that should by all means work).

I don't know how to ping the CC3000 using UDP (would love to hear an explanation if you think it's not too complicated to understand, for someone like me who has no experience with this), but I attached a PING test to the CC3000.
See attached picture: "CC3000 PING from PC.jpg"

Let me know if you need anything else.

Thanks in advance!

Smartphone PING from PC.jpg

CC3000 PING from PC.jpg

Ramirez7:
I am a Mechanical engineer with little knowledge about network.

OK.

So I will try to leave out the gobbledygook and explain more.

On a low level in your environment you have Ethernet (via cable (LAN) and wireless (WLAN)).

On top of that (using Ethernet) runs the IP protocol.
(IP addresses (4 bytes for IP-4) have a network part (upper part) and a node part (lower part)
the notation xx.xx.xx.xx just denotes these four bytes in decimal, the subnetmask defines the splitting.
default gateway is the node that gets packets that do not reside in the same subnetwork as the sender.
The 192.168. beginning of your IP addresses mark these as lokal ('non-internet'),
which is absolutly OK.)

UDP is an IP packet protocol that works without acknowledgements (and connectionless).
UDP packets can be received from/send to any node.

TCP is an IP stream protocol that works with acknowledgments and flowcontrol.
TCP packets will only come from/go to the node the connection was established with.

Most servers use TCP (webservers mostly port 80).

There is no difference between LAN, WLAN, or 'internet' in respect to communication.

ping is a utility that sends UDP packets to a mini 'server'
(builtin the IP environment for testing purposes).
The 'server' echos the received packet and ping shows you details
for each of the 4 (default) packets of 32 bytes (again the default) roundtrip.

tracert is a utility that shows the way a packet (again UDP) takes,
by making each passing entity sending back some information (as time and IP address of the entity)
when putting the packet on another network on the way to the destination.
Try it, its fun 'tracert arduino.cc'
(even if its functionality seems to be less supported in the 'days of the cloud'.)

But back to your problem:

The ping-pictures show that you have at least two subnetworks,
one for the LAN (192.168.2) and one for the WLAN (192.168.3),
nothing special or wrong with that.

So the communication seems to work (looking at the pings),
the 'start TCP connection' packet should reach the server node.

WireShark can filter for ports, ip addresses, ... so you should be able to verify that
and see an eventual response from C#.

Thanks for the thorough explanation Whandall!

Our IT guy visited today, and I asked him to have a look.

It seems that in order to not let customers be able to see the contents of our PCs when they connect to the office WiFi, he intentionally separated between the LAN and WLAN. i.e. the subnetwork for our
PCs is 192.168.2.X
while for all the wireless devices
it is 192.168.3.X

This means, according to him, that there is absolutely no way I could send data from the wireless Arduino (192.168.3.X)

to my PC (192.168.2.X)

because they just don't "see" each other.

Do you think he is right?

The whole project is based on sending wireless data to all the computers in the office.

Is there something that can be done?

Thanks again!

Not believing the sys-admin is generally a bad idea, because he configures the system,
but your second ping jpg tells a different story (PC pings CC3000),
in the first you blanked out the subnet, so I can only guess that it works in the other direction also.

So at least UDP ping traffic is able to make it to the other subnet.
(That is not my understanding of 'there is no way' or 'just don't "see" each other').

TCP could be configured different, even UDP could be limited to ping traffic.

So it seems, trusting in the IT guy, to be impossible.

I would still verify that there is no detectable TCP traffic coming from the WLAN,
but I'm a very skeptical person ;), seeing is believing.

If the problem is the network configuration, that could be changed.
You run a second WLAN (different subnet) with PC subnet access,
that only special devices may join, selected by the individual MAC address of each device.
Both variants need the sys-admin and his good will (and/or a management decision).

I hope you got at least a little better understanding of the network stuff.

Thanks Whandall!

I did get a little better understanding of the network stuff :slight_smile:

I am getting very frustrated with this not working though, and while trying to think of other ways of sending the data, I thought about simplifying the communication by going for the UDP protocol, instead of TCP.

My intention is to send binary information only, i.e "0" or "1"... from the Wireless Arduino to the PCs, and if I understand correctly a UDP protocol can handle such small data delivery, and is much more simple.

Can UDP bypass this separation between the LAN and WLAN subnetworks?

I tried to use the

client.connectUDP(server, 67)

DHCP clients (CC3000 WiFi) send messages to the server on port 67

And DHCP server (PC) sends messages to clients on port 68.

So I monitored port 68 on my PC with Wireshark. When CC3000 executed this line of code I wrote above, Wireshark showed a couple of lines.
Please see the attached pic: "UDP From Arduino.jpg"

What was most exciting for me was to see the blue line at the bottom of the picture:

Your (client) IP address: 192.168.3.184 (192.168.3.184)

This is the CC3000 IP! :slight_smile:

So it looks like a progress... the PC could communicate with the CC3000.

So does it mean that now I only have to implement in the code functions that will send data in UDP?
Do you have any idea on where to look for those functions and how to use them?

I tried to look in the CC3000 library, and search for the term UDP,
but except for the client.connectUDP() function, I couldn't find functions that actually send data using UDP.

If you want you can have a look at the SparkFun CC3000 gitHub repository here:
SFE_CC3000_Library

I would really appreciate your help, as you are the only one who answered so far...

What am I missing?

Hello Ramirez,

you will not have any feedback of the successful reception of an UDP packet in the protocol,
so you would have to come up with a software schema, if needed, but you could use it, shure.

I'm a litte irritated that you have been able to see DHCP traffic connected to the CC3000,
but that could be an inter-router stuff I'm not aware of.

I would suggest (do I repeat myself?) to wireshark (filter for CC3000's ip or subnet)
some pings to the CC3000 and from the CC3000 if you can find a sketch that pings.
Also try the planned access using TCP (in the case the IT-guy was wrong).
You should see the ping requests and replys.

If you see the TCP request, you have to find out why C# does not get it.

If not, investigate the UDP side:

How to send an UDP packet could be seen in the above sketch (if you found it),
or somewhere in the forum, I'm quite shure you are not the first who wants to use that.
(for one discussion on supporting the TI CC3000 WiFi module - #105 by system - Other Hardware Development - Arduino Forum post #99)

Try to send an UDP packet to different (from ping) ports from the CC3000 to the PC.
If you can see these packets in wireshark, UDP is not blocked and usable.

If you can see ping packets only, maybe it is possible to intercept/detect those and use the echo data as means of communication.

Many ifs...