Digole OLED Realtime Stream From UDP server (local connection)

So I have been experimenting with Spark Core and its realtime capabilities. I must say it SUCKS!

I ended by sending 10x8 pixels in one UDP packet (80 bytes). My PC is streaming a 10x8 area of predefined pixels unique for each packet. Spark Core will render about 30 screens, then it will hang with cyan light flashing, which means it could not ping the cloud or whatever.

Ok, so I added some delay between each UDP packet on my PC server.

  1. Thread.Sleep(10) = HANG
  2. Thread.Sleep(50) = HANG
  3. Thread.Sleep(100) = SEEMS TO NOT HANG

Updating the core with few more packets looks like DDOS attack :frowning:

I was trying both TCP and UDP. TCP send like one packet in an hour o_0. Also documentation for TCPclient says client.read() returns -1 when no data, but I never got -1 when saving to int value. For UDP the read() method says it returns the next byte. But does not say what does it return when there’s no next byte.

/* Uncomment the #define below for the desired interface: SPI, SoftSPI, I2C, UART. */

#define _Digole_Serial_SPI_
//#define _Digole_Serial_SoftSPI_
//#define _Digole_Serial_I2C_
//#define _Digole_Serial_UART_

/* Be sure to #include "DigoleSerialDisp.h" *after* the #define above or your compile will fail. */

#include "DigoleSerialDisp.h"

/* Below are sane defaults for the various interfaces. Uncomment one and customize as needed! */

DigoleSerialDisp digole(A2); //SPI
//DigoleSerialDisp digole(D4, D3, D2); //SoftSPI
//DigoleSerialDisp digole(0x27); //I2C
//DigoleSerialDisp digole(115200); //UART

const uint8_t w = 160;
const uint8_t h = 128;
const uint8_t wChunk = 10;
const uint8_t hChunk = 8;
const uint16_t bufferSize = wChunk*hChunk;
const uint16_t localPort = 9000; 

uint16_t bytesRead = 0;
uint16_t bytesPos = 0;
uint8_t bitmapData[bufferSize];
UDP client;
byte server[] = { 192, 168, 1, 65 };


void setup() {
	Serial.begin(9600);
	client.begin(localPort);
	digole.begin();
	digole.clearScreen();
	//digole.print("LOADING...");
	for (uint16_t x = 0; x < bufferSize; x++) {
        bitmapData[x] = 60;
    }
        
	digole.drawBitmap256(0, 0, wChunk, hChunk, bitmapData);
}

void loop() {
    uint16_t bytesRead = client.parsePacket();
    
    if (bytesRead > 0) {
            //for (uint16_t x = bytesPos; x < bytesRead; x++) {
                int byteRead = 0;
                byteRead = client.read();
                if (byteRead == -1) {
                    Serial.println("BYTE END");
                } else if (bytesPos < bufferSize) {
                    bitmapData[bytesPos] = byteRead;
                    //Serial.print("b=");
                    //Serial.println(bitmapData[bytesPos]);
                    bytesPos++;
                }
            //}

    }
        if (bytesPos >= bufferSize) {
            Serial.print("bytesPos=");
            Serial.println(bytesPos);
            bytesPos = 0;
            digole.drawBitmap256(0, 0, wChunk, hChunk, bitmapData);
        }
}

I’ve lost two weeks of daily work, because I trusted the core that it can do more than just silly read/write one value per minute. I have to put a specific Spark delay on my PC UDP server, then SPI has some delay when writing data. Loop function has some other delays behind the scenes and then there’s that silly cloud I didn’t even request when ordering or reading about Spark. SRSLY I don’t care about money, I want next-gen tech devices. Looks like classic Arduino+Zigbee, Arduino Yun or dual-core ARM Cortex+dual-core GPU will be better.

BTW: This was possible in 2011 on Arduino with ATMEL: http://q61.org/en/chibimo/build/ …now it’s 2014 and I’m slowed down by some additional software bloat I didn’t even want.

There was something wrong with your code, related to TCP I assume. I personally was able to send ~10 TCP GET requests per second. Didn't try more frequesnt requests, but It took less than 500 microseconds per request on LAN.

Never tried UDP, though

Hi @cyberluke,

I wonder if you’re not running into the CFOD problem, essentially. (Potentially unnecessary recap) There is a bug with the CC3000 that we’re working with TI to fix at the moment.

Essentially it looks like the CC3000 suffers from buffer exhaustion when bombarded by very high traffic on its network. If you’re streaming realtime display data in the form of UDP packets, it’s reasonable to me that you could be easily knocking your core offline.

TI has already released one driver upgrade for the CC3000 this last week in response to this issue, and we’re working with them to fix the root cause of the CFOD problem. I’m thinking will make a big difference on the volume of traffic your project can handle.

Oh, I thought that CFOD problem was already in the master branch. I have upgraded CC3000 firmware once in past two weeks and there was that fix for 10.0.0.0 networks login issue. I’m sharing a project in other thread in few minutes. It will be a Syma S107 two-channel RC helicopter controlled with any DirectInput (joystick, gamepad, wheel, etc.) over C# .NET UDP server.

1 Like

Yeah, that one hour was ironic :slight_smile: It was like 1 TCP request in 20 seconds. I tried also a TCP.NoDelay option in TCP server, which disables Nagle’s algorithm, which can reduce latency from 40ms to 1ms on TCP connection (http://en.wikipedia.org/wiki/Nagle’s_algorithm).

I was getting bad TCP rate when I was handling it incorrectly :slight_smile:
Have you considered using WebSocket solution instead of UDP? It is TCP based and should be more relieable.

1 Like

I wrote some UDP servers already. UDP is better for realtime data. 3D games use it for player position, because if the packet is to be thrown away, it does not matter, because player position already changed and it will be up2date in the next UDP packet. The same applies for RC helicopter position or for desktop screen. So UDP is really great for this. TCP is better when uploading image for example - where you need data consistency, but don’t care about latency for realtime systems.

Today I found a tablet for $38, which is $1 cheaper than Spark Core and it can run Linux, which means it could be pretty easily used as a wireless display (don’t need 3G and gyro stuff for this): http://linuxgizmos.com/38-android-tablet-the-new-price-king/