WiFi module with an SPI interface- project...

Status
Not open for further replies.
I'm now confident that the board, firmware, library, and Teensy 3 are all playing nice now so I can finally start working on a web server. More details soon....

Any updates on this? I'm actually more interested in the UDP side of things (want the CC3000 and Teensy 3.0 to act as a UDP server), but progress is progress ;)
 
Work progresses, slowly but surely.

Because the CC3000 library is pretty low-level Berkeley sockets, a UDP server won't look very much like a TCP server so I'm not sure how much help webserver code will be for you.

For UDP you'd follow these steps:

1. Allocate a UDP socket
2. Bind it to a UDP port
3. Set socket options to nonblocking (optional, will depend on your code flow)
4. Loop in recvfrom() or send(), depending on your code flow

Here's some code I just found that will be pretty close to what you want to do. It's Linux C, so the #includes and prints will obviously be different, but the network code should be pretty close:

http://www.abc.se/~m6695/udp.html

Good luck!
 
Hey Guys,
i can't get the serial monitor to work with a teensy 3, i downloaded the last version of the lib, or tried to change some lines as mentioned on a previous page but nothing ...
its working perfectly with an UNO board .

@jimmayhugh would you mind sharing your UDPapp example ?

thank you!
 
update: i am running the IDE 1.0.5 on a osx 10.8.5, none of the example from the library got the serial monitor working.
 
Hey Guys,
i can't get the serial monitor to work with a teensy 3, i downloaded the last version of the lib, or tried to change some lines as mentioned on a previous page but nothing ...
its working perfectly with an UNO board .

@jimmayhugh would you mind sharing your UDPapp example ?

thank you!

Added to Adafruit_CC3000.h:
Code:
class Adafruit_CC3000_Server : public Print {
 public:
  Adafruit_CC3000_Server(uint16_t s);
  Adafruit_CC3000_Server(void);
  
  bool connected(void);
  size_t write(uint8_t c);

  size_t fastrprint(const char *str);
  size_t fastrprintln(const char *str);
  size_t fastrprint(const __FlashStringHelper *ifsh);
  size_t fastrprintln(const __FlashStringHelper *ifsh);

  int16_t write(const void *buf, uint16_t len, uint32_t flags = 0);
  int16_t read(void *buf, uint16_t len, uint32_t flags = 0);
  uint8_t read(void);
  int32_t close(void);
  uint8_t available(void);

  uint8_t _rx_buf[RXBUFFERSIZE], _rx_buf_idx;
  char    _tx_buf[TXBUFFERSIZE];
  int16_t bufsiz;

 private:
  int16_t _socket;

};

Adafruit_CC3000.cpp:
Code:
Adafruit_CC3000_Server Adafruit_CC3000::connectAndBindUDP(uint32_t destIP, uint16_t destPort)
{
  sockaddr      socketAddress;
  uint32_t      udp_socket;

  // Create the socket(s)
  // socket   = SOCK_STREAM, SOCK_DGRAM, or SOCK_RAW 
  // protocol = IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW
  //if (CC3KPrinter != 0) CC3KPrinter->print(F("Creating socket... "));
  udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  if (-1 == udp_socket)
  {
    CC3KPrinter->println(F("Failed to open socket"));
    return Adafruit_CC3000_Server();
  }
  //if (CC3KPrinter != 0) { CC3KPrinter->print(F("DONE (socket ")); CC3KPrinter->print(udp_socket); CC3KPrinter->println(F(")")); }

  // Try to open the socket
  memset(&socketAddress, 0x00, sizeof(socketAddress));
  socketAddress.sa_family = AF_INET;
  socketAddress.sa_data[0] = (destPort & 0xFF00) >> 8;  // Set the Port Number
  socketAddress.sa_data[1] = (destPort & 0x00FF);
  socketAddress.sa_data[2] = destIP >> 24;
  socketAddress.sa_data[3] = destIP >> 16;
  socketAddress.sa_data[4] = destIP >> 8;
  socketAddress.sa_data[5] = destIP;

  if (CC3KPrinter != 0) {
    CC3KPrinter->print(F("Connect to "));
    printIPdotsRev(destIP);
    CC3KPrinter->print(':');
    CC3KPrinter->print(destPort);
    CC3KPrinter->print(F(", Socket: "));
    CC3KPrinter->println(udp_socket);
  }

  //printHex((byte *)&socketAddress, sizeof(socketAddress));
  if (-1 == bind(udp_socket, &socketAddress, sizeof(socketAddress)))
  {
    if (CC3KPrinter != 0) CC3KPrinter->println(F("Connection error"));
    closesocket(udp_socket);
    return Adafruit_CC3000_Server();
  }

  return Adafruit_CC3000_Server(udp_socket);
}


/**********************************************************************/
Adafruit_CC3000_Server::Adafruit_CC3000_Server(void) {
  _socket = -1;
}

Adafruit_CC3000_Server::Adafruit_CC3000_Server(uint16_t s) {
  _socket = s; 
  bufsiz = 0;
  _rx_buf_idx = 0;
}

bool Adafruit_CC3000_Server::connected(void) { 
  if (_socket < 0) {
    // if (CC3KPrinter != 0) CC3KPrinter->println("connected() - _socket < 0");
    return false;
  }

  if (! available() && closed_sockets[_socket] == true) {
    // if (CC3KPrinter != 0) CC3KPrinter->println("No more data, and closed!");
    closesocket(_socket);
    closed_sockets[_socket] = false;
    _socket = -1;
    return false;
  }

  else return true;  
}

int16_t Adafruit_CC3000_Server::write(const void *buf, uint16_t len, uint32_t flags)
{
  return send(_socket, buf, len, flags);
}


size_t Adafruit_CC3000_Server::write(uint8_t c)
{
  int32_t r;
  r = send(_socket, &c, 1, 0);
  if ( r < 0 ) return 0;
  return r;
}

size_t Adafruit_CC3000_Server::fastrprint(const __FlashStringHelper *ifsh)
{
  uint8_t idx = 0;

  const char PROGMEM *p = (const char PROGMEM *)ifsh;
  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte(p++);
    if (c == 0) break;
    _tx_buf[idx] = c;
    idx++;
    if (idx >= TXBUFFERSIZE) {
      // lets send it!
      n += send(_socket, _tx_buf, TXBUFFERSIZE, 0);
      idx = 0;
    }
  }
  // reached the end before filling the buffer completely
  n += send(_socket, _tx_buf, idx, 0);

  return n;
}

size_t Adafruit_CC3000_Server::fastrprintln(const __FlashStringHelper *ifsh)
{
  size_t r = 0;
  r = fastrprint(ifsh);
  r+= fastrprint("\n\r");
  return r;
}

size_t Adafruit_CC3000_Server::fastrprintln(const char *str)
{
  size_t r = 0;
  if ((r = write(str, strlen(str), 0)) <= 0) return 0;
  if ((r += write("\n\r", 2, 0)) <= 0) return 0;  // meme fix
  return r;
}

size_t Adafruit_CC3000_Server::fastrprint(const char *str)
{
  return write(str, strlen(str), 0);
}


int16_t Adafruit_CC3000_Server::read(void *buf, uint16_t len, uint32_t flags) 
{
  return recv(_socket, buf, len, flags);

}

int32_t Adafruit_CC3000_Server::close(void) {
  int32_t x = closesocket(_socket);
  _socket = -1;
  return x;
}

uint8_t Adafruit_CC3000_Server::read(void) 
{
  while ((bufsiz <= 0) || (bufsiz == _rx_buf_idx)) {
    cc3k_int_poll();
    // buffer in some more data
    bufsiz = recv(_socket, _rx_buf, sizeof(_rx_buf), 0);
    if (bufsiz == -57) {
      close();
      return 0;
    }
    //if (CC3KPrinter != 0) { CC3KPrinter->println("Read "); CC3KPrinter->print(bufsiz); CC3KPrinter->println(" bytes"); }
    _rx_buf_idx = 0;
  }
  uint8_t ret = _rx_buf[_rx_buf_idx];
  _rx_buf_idx++;
  //if (CC3KPrinter != 0) { CC3KPrinter->print("("); CC3KPrinter->write(ret); CC3KPrinter->print(")"); }
  return ret;
}

uint8_t Adafruit_CC3000_Server::available(void) {
  // not open!
  if (_socket < 0) {
    // if (CC3KPrinter != 0) CC3KPrinter->println("available() - _socket < 0");
    return 0;
  }

  if ((bufsiz > 0) // we have some data in the internal buffer
      && (_rx_buf_idx < bufsiz)) {  // we havent already spit it all out
    // if (CC3KPrinter != 0) CC3KPrinter->println("available() - data in buffer");
    return (bufsiz - _rx_buf_idx);
  }

  // do a select() call on this socket
  timeval timeout;
  fd_set fd_read;

  memset(&fd_read, 0, sizeof(fd_read));
  FD_SET(_socket, &fd_read);

  timeout.tv_sec = 0;
  timeout.tv_usec = 5000; // 5 millisec

  int16_t s = select(_socket+1, &fd_read, NULL, NULL, &timeout);
  //if (CC3KPrinter != 0) } CC3KPrinter->print(F("Select: ")); CC3KPrinter->println(s); }
  if (s == 1) {
    return 1;  // some data is available to read
  }else{
    // if (CC3KPrinter != 0) CC3KPrinter->println("available() - no data is available");
    return 0;  // no data is available
  }
}

Setup code:
Code:
Adafruit_CC3000_Server server;
                                         
// Local server IP, port, and repository (change with your settings !)
unsigned int localPort = 2652;      // local port to listen on

setup()
{
  if(setDebug & udpDebug)
  {
    Serial.println(F("Initializing CC3000 nic"));
  }
  // Initialise the CC3000 module
  if (!cc3000.begin())
  {
    while(1);
  } 

// Per http://e2e.ti.com/support/low_power_rf/f/851/t/292664.aspx
// aucInactivity needs to be set to 0 (never timeout) or the socket will close after
// 60 seconds of no activity
  unsigned long aucDHCP       = 14400;
  unsigned long aucARP        = 3600;
  unsigned long aucKeepalive  = 30;
  unsigned long aucInactivity = 0;
  if(aucInactivity == 0)
  {
    Serial.println(F("Setting netapp to not timeout..."));
  }else{
    Serial.print(F("Setting netapp to timeout in "));
    Serial.print(aucInactivity);
    Serial.println(F(" Seconds"));
  }
  long iRet = netapp_timeout_values(&aucDHCP, &aucARP, &aucKeepalive, &aucInactivity);
  if (iRet!=0)
  {
    Serial.print(F("Could not set netapp option, iRet = "));
    Serial.println(iRet);
    Serial.println(F(", aborting..."));
    while(1);
  }else{
    Serial.print(F("set netapp option, iRet = "));
    Serial.println(iRet);
  }

  displayMACAddress();
  
  // Connect to  WiFi network
  cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY);
  Serial.println("Connected to WiFi network!");


  // Check DHCP
  Serial.print(F("Requesting address from DHCP server..."));
  for(t=millis(); !cc3000.checkDHCP() && ((millis() - t) < dhcpTimeout); delay(1000));
  if(cc3000.checkDHCP()) {
    Serial.println(F("OK"));
    displayConnectionDetails();
  } else {
    Serial.println(F("failed"));
    return;
  }

  timer = millis();
  timer2 = millis();
  
  for(int q = 0; q < UDP_TX_PACKET_MAX_SIZE; q++) // clear the buffer udp buffers
  {
    ReplyBuffer[q] = 0x00;
    PacketBuffer[q] = 0x00;
  }
  unsigned long startTime;

  Serial.println(F("Attempting connection..."));
  
  startTime = millis();
    
    do
    {
      server = cc3000.connectAndBindUDP(0x0, localPort);
    } while((!server.connected()) &&
            ((millis() - startTime) < connectTimeout));

    if(server.connected())
    {
      Serial.println(F("connected!"));
      server.println("@");
    }else{
      Serial.println(F("NOT connected!"));
      while(1);
    }
}

loop()
{
  while(server.available())
  {
    char c = server.read();
    
    if(c != 0x00)
    {
      PacketBuffer[rpBufferCnt] = c;
      if(PacketBuffer[rpBufferCnt] == '\n')
      {
        if(setDebug & udpDebug)
        {
          Serial.print(PacketBuffer);
        }
        break;
      }else{
        rpBufferCnt++;
      }
    }
  }
  if(PacketBuffer[0] != 0x00)
  {
    udpProcess();
  }
}
 
@jimmayhugh hey i seen you were looking for a way to setup a static ip to the cc3000, did you finally found a way to do it with the arduino IDE or using the terminal and the cc3000 uart ??
cheerios
 
T.I. docs say
For the static IP configuration, the NetappDHCP API call is triggered with a non-0 IP address and subnetmask parameters. Otherwise, the 0 IP address is passed to the API call and informs a device that DHCP must be used. The following figure shows the required behavior.
 
Paul,

I am trying to get the cc3000 breakout board from Adafruit hooked up to the Teensy 3.0. Thanks for posting the wiring above. From what I can tell the termination is as follows:

cc3000-teensy 3.0
CLK-13
MISO-12
MOSI-11
CS-10
VBLEN-5
IRQ-3

Just having trouble hooking up the power. Not too experienced on the electrical side. Do you have all those pins going to ground after termination to the Teensy? From what I read the cc3000 consumes 275mA, which will be too much for the Teensy 3.0 to deliver(100mA max). I have an Arduino 328p and 3.3V(https://www.sparkfun.com/products/526) regulator at my disposal. Could you let me know how to hook it up? Do I need to modify the Teensy?

Thanks,

-ren
 
The pin connections are correct. If you want to be really pedantic you can use any available pins for CS, VBLEN, and IRQ, but it's probably safest to get it working first with Adafruit's default pin usage.

I'm a little confused by "do you have all those pins going to ground after termination to the Teensy", but no you would only connect ground on the Teensy 3 to ground on the CC3000 board. You definitely wouldn't ground the SPI, IRQ etc. pins.

If you're powering the Teensy 3 via USB then you'd run the 5V coming off the Teensy 3's VIN pin into your voltage regulator, then the 3.3V from the regulator into the 3V3 pin of the CC3000 board. The Adafruit CC3000 board has its own regulator but I believe if you run 5V into its VIN then the data pins will also be 5V, which is not good for the 3V3 only Teensy 3.

Good luck!
 
Potatotron,
leads.jpg
Thanks for the info. The question about running the leads from the teensy to ground came from leads(pointed to with a red arrow) attached.

Thanks,

-ren
 
Potatotron is correct, I wired the CC3000 VIN pin to Teensy3's VIN pin. The "3.3V" pin on CC3000 is not connected.

Those prototype boards I use have a ground plane on the top side. The short wire you see in the photo is just a solder connection through a nearby hole to the top side.
 
Any particular reason that the is5100() and is5200() functions are private? I'm working with a board that I designed that can be used with the WIZ812mj, WIZ820io or the Adafruit CC3000 breakout board, and I'm trying to make my code recognize which nic is installed, since it appears that the max udp packet size varies widely for each device.
 
The MAX IP packet size, regardless of TCP, UDP, ICMP, can be the standard MTU size as I recall from working with the 812MJ. The UDP packet is sent to the host with a header (proprietary format) that shows the source IP, Socket, etc.
 
stevech is right, the max packet size is the same for All Things Ethernet, ~ 1500 bytes. Things are a little weirder than that because actually the IP stack is supposed to hide the packet size from the higher-level protocols; the official maximum datagram size for UDP is 64K. In practice, especially for smaller MCUs like the CC3000, maximum UDP size = maximum Ethernet size = about 1500 bytes (I say 'about' because the actual number depends on if you're talking about data payload, actual frame size including vlan info etc., etc. etc. etc.).

jimmayhugh, I think what you may be seeing is the default size of the Adafruit library's buffer which I think is about 130 bytes? The CC3000 & library doesn't have any ability to fragment packets so if you tried to send 1000 bytes it won't send 8 packets, it will just send 1 and discard the extra data.

If you're using the Teensy3 you don't have the RAM limit a regular Arduino has, try increasing the buffer size in cc3000_common.h.
 
Actually what I'm looking at is the defined size of UDP_TX_PACKET_MAX_SIZE in EthernetUDP.h, which is set at 24 bytes. I'm aware of the restriction in the CC3K, and have a work-around for that.
 
Any particular reason that the is5100() and is5200() functions are private?

Not really, other than there's no API in the Ethernet library regarding the underlying hardware. I wanted to make it "just work" with either chip.

Should they be "protected" or "public" instead of "private"? Most of the other methods that direct access the hardware are private.
 
Actually what I'm looking at is the defined size of UDP_TX_PACKET_MAX_SIZE in EthernetUDP.h, which is set at 24 bytes. I'm aware of the restriction in the CC3K, and have a work-around for that.

My mistake. I didn't know we were talking about a non-CC3000 board.

On the other hand...24 bytes...?
 
Ok, I know lots of UDP stuff using more than 24 bytes actually works.

I just did a little searching. It seems UDP_TX_PACKET_MAX_SIZE is not actually used anywhere within the Ethernet library. It is used in the UDPSendReceiveString.ino example. Why it's defined inside the library for only an example is a mystery. Maybe that #define is a leftover an early version used a fixed buffer?

The actual UDP code does not appear to have any built-in limit, other than the limits imposed by the W5100/W5200 chip. Here's the UDP write code. The "bufferData" function copies right into the W5100.

Code:
size_t EthernetUDP::write(uint8_t byte)
{
  return write(&byte, 1);
}

size_t EthernetUDP::write(const uint8_t *buffer, size_t size)
{
  uint16_t bytes_written = bufferData(_sock, _offset, buffer, size);
  _offset += bytes_written;
  return bytes_written;
}
 
becuause Wiznet adds the header bytes (prepends), the host has to expect these extra bytes.

For me, the hardest part of the '5100 code was to make TCP streams so that packet boundaries are hidden. But I was working in bare-metal, no libraries.
 
Is there a way to get the SPI running @ 8Mhz on the teensy 3.0 board? If not I guess the closest I can get to this is 12Mhz , correct?

Thanks,

-ren
 
Status
Not open for further replies.
Back
Top