Less than $3 WiFi chip

the testing is currently running on ESP-3 and I also have the ESP-1 which i’ll test when i reach a million requests and replies :wink: . but i don’t think it matters to be honest!

latest firmware released today:
http://bbs.espressif.com/viewtopic.php?f=5&t=286

make sure you read the docs included in the above download as the API and the AT commands have changed !

cheers,
Jay

1 Like

@ Jay Jay - Will you share the driver?

I don’t have a driver per say but I use the following code to test the chip:

Edit: new and improved code here:
https://www.ghielectronics.com/community/forum/topic?id=17007&page=24#msg185759

the above is used to test the server piece of the module, it should be a good starting point.

Cheers,
Jay.

3 Likes

The firmware has now reached the v1.0 mark! Enjoy!

http://bbs.espressif.com/viewtopic.php?f=5&t=286

They are offering a bounty if someone finds a new bug!

http://bbs.espressif.com/viewtopic.php?f=5&t=288

1 Like

Feels like it is a reliable solution now.

a new and improved code :), this one is using Events instead of the Queue and the continuous while() to read the Queue…


...Program.cs

using System;
using System.Threading;
using Microsoft.SPOT;
using System.IO.Ports;
using Microsoft.SPOT.Hardware;
using System.Text;


namespace ESP8266Wifi
{
    public partial class Program
    {
        private static readonly int SerialPortCount = HardwareProvider.HwProvider.GetSerialPortsCount();
        private static bool _softRest;

        ..private const string Apssid = "SSID";
        ..private const string Password = "PASSWORD";
        ..private static readonly SerialPort Esp = new SerialPort("COM2", 115200, Parity.None, 8, StopBits.One);//update the COM Port Number
        ..private static readonly OutputPort Led = new OutputPort((Cpu.Pin) 78, false); //Mountaineer Ethernet Board
        ..private static readonly OutputPort LedRed = new OutputPort((Cpu.Pin) 77, false); //Mountaineer Ethernet Board
        private static SerialBuffer _mySerialBuffer;
        public static AutoResetEvent SerialBlocking = null;
        private static int _pageCounter;
        private static int _rebootCounter;
        private static int _channelId;
        //private const string UDPBroadcastIP = "239.255.255.250";// "0.0.0.0";//
        //private const string BroadcastPort = "1900";//"0";//

        public delegate void DataProcessorHandler(string data, SerialPort port);

        public static event DataProcessorHandler DataProcessor;
        // The method which fires the Event
        protected static void OnDataProcessor(string data, SerialPort port)
        {
            // Check if there are any Subscribers
            if (DataProcessor != null)
            {
                // Call the Event
                DataProcessor(data, port);
            }
        }

        public static void Main()
        {

            Debug.Print("Serial Port Count is: " + SerialPortCount);
            DataProcessor += Communication;
            _mySerialBuffer = new SerialBuffer(512);
            // Init the sync
            SerialBlocking = new AutoResetEvent(false);

            // Setup the receiver
            Esp.ErrorReceived += esp_ErrorReceived;
            Esp.ReadTimeout = 10;
            // Open the serial port
            Esp.Open();
            Esp.DiscardInBuffer();
            Esp.DataReceived += wifi_DataReceived;

            Thread.Sleep(1000);
            new Thread(TestEsp).Start();
            Debug.Print("Program Started");


            //keep the program running
            Thread.Sleep(Timeout.Infinite);
        }

        public static void Blink()
        {
            while (true)
            {
                LedRed.Write(!LedRed.Read());
                Thread.Sleep(500);
            }
        }

        private static void esp_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {
            Debug.Print("NetMF Error=" + e.EventType.ToString());
            Esp.DiscardInBuffer();
        }

        public static void TestEsp()
        {

            Debug.Print("TestEsp Started");

            byte[] cmd = Encoding.UTF8.GetBytes("AT\r\n");
            Esp.Write(cmd, 0, cmd.Length);

            // Wait for the command to be completed
            SerialBlocking.WaitOne();

            //resets the module only during first boot.

            if (!_softRest)
            {
                _softRest = true;
                cmd = Encoding.UTF8.GetBytes("AT+RST\r\n");
                Esp.Write(cmd, 0, cmd.Length);
                // Wait for the command to be completed
                SerialBlocking.WaitOne();
            }

            //Thread.Sleep(100);

            // Query firmware version
            //cmd = Encoding.UTF8.GetBytes("AT+GMR\r\n");
            //Esp.Write(cmd, 0, cmd.Length);

            //// Wait for the command to be completed
            //SerialBlocking.WaitOne();

            Thread.Sleep(100);
            // Set wifi mode 3 = Client and Soft AP
            cmd = Encoding.UTF8.GetBytes("AT+CWMODE=3\r\n");
            Esp.Write(cmd, 0, cmd.Length);

            // Wait for the command to be completed
            SerialBlocking.WaitOne();

            Thread.Sleep(100);
            // Set the Soft AP
            cmd = Encoding.UTF8.GetBytes("AT+CWSAP=\"COOLAP2\",\"21030826\",5,0\r\n");
            Esp.Write(cmd, 0, cmd.Length);

            // Wait for the command to be completed
            SerialBlocking.WaitOne();

            Thread.Sleep(100);
            // AT+CWLAP = List access points
            cmd = Encoding.UTF8.GetBytes("AT+CWLAP\r\n");
            Esp.Write(cmd, 0, cmd.Length);

            // Wait for the command to be completed
            SerialBlocking.WaitOne();

            Thread.Sleep(100);
            // Join an access point
            cmd = Encoding.UTF8.GetBytes("AT+CWJAP=\"" + Apssid + "\",\"" + Password + "\"\r\n");
            Esp.Write(cmd, 0, cmd.Length);

            // Wait for the command to be completed
            SerialBlocking.WaitOne();

            Thread.Sleep(100);
            // Show IP address
            cmd = Encoding.UTF8.GetBytes("AT+CIFSR\r\n");
            Esp.Write(cmd, 0, cmd.Length);

            // Wait for the command to be completed
            SerialBlocking.WaitOne();

            Thread.Sleep(100);
            //change it to multiple mode connection required to start a server
            cmd = Encoding.UTF8.GetBytes("AT+CIPMUX=1\r\n");
            Esp.Write(cmd, 0, cmd.Length);
            // Wait for the command to be completed
            SerialBlocking.WaitOne();

            Thread.Sleep(100);
            // Start the server port 80
            cmd = Encoding.UTF8.GetBytes("AT+CIPSERVER=1,80\r\n");
            Esp.Write(cmd, 0, cmd.Length);
            // Wait for the command to be completed
            SerialBlocking.WaitOne();

            //Thread.Sleep(100);
            //set timeout
            cmd = Encoding.UTF8.GetBytes("AT+CIPSTO=20\r\n");
            Esp.Write(cmd, 0, cmd.Length);
            //  Wait for the command to be completed
            SerialBlocking.WaitOne();

            //UDP testing for later
            // cmd = Encoding.UTF8.GetBytes("AT+CIPSTART=4,\"UDP\",\"" + UDPBroadcastIP + "\"," + BroadcastPort + ",1002,2" + "\r\n");//+ "\",\"" + "2023\"" + ",1\r\n");//
            // Esp.Write(cmd, 0, cmd.Length);
            // Wait for the command to be completed
            //SerialBlocking.WaitOne();

            _softRest = false;
            SerialBlocking = null;
            new Thread(Blink).Start();

        }

        private static void wifi_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                if (e.EventType == SerialData.Chars)
                {

                    int RS232Count;
                    int arraySize = 512;
                    byte[] received = new byte[arraySize];
                    var port = sender as SerialPort;

                    if (port != null)
                    {
                        arraySize = port.BytesToRead;
                        RS232Count = port.Read(received, 0, arraySize);

                        if (RS232Count > 0)
                        {
                            _mySerialBuffer.LoadSerial(received, 0, RS232Count);
                            string dataLine;
                            while ((dataLine = _mySerialBuffer.ReadLine()) != null)
                            {
                                OnDataProcessor(dataLine, port);
                            }

                        }
                    }

                }

            }
            catch (Exception ex)
            {

                Debug.Print("DataReceive Error:" + ex.Message);

            }
        }




        public static void Communication(string dataReceived, SerialPort port)
        {
            try
            {

                if (dataReceived.IndexOf("busy s..") != -1)
                {

                    // Debug.Print("************************************Busy**************************************");
                    // Thread.Sleep(10);
                    //var cmd = Encoding.UTF8.GetBytes("AT+CIPCLOSE=" + _channelId + "\r\n");//"AT+RST" + "\r\n");
                    //lock (Esp)
                    //{
                    // 
                    // Esp.Flush(); //clear the buffer  
                    //Esp.DiscardInBuffer();
                    //Esp.DiscardOutBuffer();
                    // Esp.Write(cmd, 0, cmd.Length);
                    //}
                }

                if (dataReceived.LastIndexOf("\r\n>") != -1)
                {

                    var strr = "<html><head><title>Welcome</title></head><body><p>Welcome " + "PageCounter" + " = " +
                               _pageCounter + " RebootCounter=" + _rebootCounter + " ChannelId=" + _channelId +
                               ".</p></body></html>";
                    var headersr = "HTTP/1.1 200 OK\r\nContent-Type: " + "text/html" + "\r\nContent-Length: " +
                                   strr.Length + "\r\nServer: " + "hostname" +
                                   "\r\nCache-Control: no-cache\r\nConnection: keep-alive\r\n\r\n"; //
                    var cmd = Encoding.UTF8.GetBytes(headersr + strr);
                    lock (port)
                    {
                        port.Write(cmd, 0, cmd.Length);
                        // port.DiscardInBuffer();
                        //Esp.Flush();
                    }
                }

                else if (dataReceived.IndexOf("+IPD") != -1)
                {

                    if (dataReceived.Length > 5)
                    {
                        _channelId = Int32.Parse(dataReceived.Substring(dataReceived.IndexOf("+IPD") + 5, 1));
                    }
                    else
                    {
                        Debug.Print("No channel found=" + dataReceived + "=" + dataReceived.IndexOf("+IPD") + "=" +
                                    dataReceived.Length);
                    }

                    // var strr = Resources.GetString(Resources.StringResources.index);
                    var strr = "<html><head><title>Welcome</title></head><body><p>Welcome " + "PageCounter" + " = " +
                               _pageCounter++ + " RebootCounter=" + _rebootCounter + " ChannelId=" + _channelId +
                               ".</p></body></html>";
                    var headersr = "HTTP/1.1 200 OK\r\nContent-Type: " + "text/html" + "\r\nContent-Length: " +
                                   strr.Length + "\r\nServer: " + "hostname" +
                                   "\r\nCache-Control: no-cache\r\nConnection: keep-alive\r\n\r\n"; //
                    //Thread.Sleep(1);
                    var cmd =
                        Encoding.UTF8.GetBytes("AT+CIPSEND=" + _channelId + "," +
                                               (int) (headersr.Length + strr.Length) +
                                               "\r\n");
                    lock (port)
                    {
                        port.Write(cmd, 0, cmd.Length);
                        //Esp.Flush();
                    }
                }
                else if (dataReceived.IndexOf("ready") != -1)
                {
                    SerialBlocking.Set();
                }
                else if (dataReceived.IndexOf("OK") != -1 || (dataReceived.IndexOf("no change") != -1))
                {

                    //Debug.Print("Found OK");
                    if (SerialBlocking != null)
                        SerialBlocking.Set();
                }
                else if (dataReceived.IndexOf("Error") != -1)
                {
                    Debug.Print("Encountered an Error");
                }
                else if (dataReceived.IndexOf("ets") != -1 && !_softRest) //detected a reset
                {
                    _rebootCounter++;
                    // Debug.Print("************************************the device just rebooted at PageCount=" + PageCounter + " RebootCounter=" + RebootCounter);
                    Led.Write(true);
                    Thread.Sleep(5000);
                    _softRest = true;
                    new Thread(TestEsp).Start();
                }
                // Debug.Print(Debug.GC(false).ToString());
                //Thread.Sleep(1);
            }
            catch (Exception)
            {
                Debug.Print("Error********************************");

            }

        }

    }
}

SerialBuffer.cs


..SerialBuffer.cs

using System;
using System.Text;

namespace ESP8266Wifi
{
    public class SerialBuffer
    {
        private readonly Decoder _decoder = Encoding.UTF8.GetDecoder();
        private int _startIndex;
        private int _endIndex;
        private char[] _charBuffer;

        public SerialBuffer(int initialSize)
        {
            Buffer = new byte[initialSize];
            _charBuffer = new char[512];
        }

        public void LoadSerial(byte[] data, int startIndex, int length)
        {
            if (Buffer.Length < _endIndex + length) // do we have enough buffer to hold this read?
            {
                // if not, look and see if we have enough free space at the front
                if (Buffer.Length - DataSize >= length)
                {
                    ShiftBuffer();
                }
                else
                {
                    // not enough room, we'll have to make a bigger buffer
                    ExpandBuffer(DataSize + length);
                }
            }
            Array.Copy(data, startIndex, Buffer, _endIndex, length);
            _endIndex += length;
        }


        private void ShiftBuffer()
        {
            // move the data to the left, reclaiming space from the data already read out
            Array.Copy(Buffer, _startIndex, Buffer, 0, DataSize);
            _endIndex = DataSize;
            _startIndex = 0;
        }

        private void ExpandBuffer(int newSize)
        {
            var newBuffer = new byte[newSize];
            Array.Copy(Buffer, _startIndex, newBuffer, 0, DataSize);
            Buffer = newBuffer;
            _endIndex = DataSize;
            _startIndex = 0;
        }

        public byte[] Buffer { get; private set; }

        public int DataSize
        {
            get
            {
                return _endIndex - _startIndex;
            }
        }

        public void ClearBuffer()
        {
            _startIndex = _endIndex;
        }
        public string ReadLine()
        {
            lock (Buffer)
            {
                // HACK: not looking for \r, just assuming that \r and \n come together        
                int lineEndPosR = Array.IndexOf(Buffer, '\n', _startIndex, DataSize);// (byte)0x0A
                int found = Array.IndexOf(Buffer, '>', _startIndex, DataSize);
                if (lineEndPosR > 0)
                {

                    int lineLength = lineEndPosR - _startIndex;
                    //added this line below to look for > when a response comes back from serving a page to ESP8266
                    if (found > 0)
                        lineLength = (lineEndPosR - _startIndex) + 3;//5

                    if (_charBuffer.Length < lineLength) // do we have enough space in our char buffer?
                    {
                        _charBuffer = new char[lineLength];
                    }

                    int bytesUsed, charsUsed;
                    bool completed;
                    _decoder.Convert(Buffer, _startIndex, lineLength, _charBuffer, 0, lineLength, true, out bytesUsed, out charsUsed, out completed);
                    var line = new string(_charBuffer, 0, lineLength - 1);
                    _startIndex = lineEndPosR + 1;

                    return line;
                }
                return null;
            }
        }
    }
}


This one runs much faster and processes the data at a very high speed…

cheers,
Jay

2 Likes

it finally Melted :frowning:

the chip no longer connects to WIFI and now gives an ERROR when I send any WIFI related AT :frowning:

I knew it was going to happen at one point… not sure what I did to kill it:( that’s the problem now :wall:

Back to the drawing board. :wink:

Actually it’s back from the dead :dance: i think it is because i tried an older firmware which resets the MODE back to 2 basically SOFTAP ONLY so after setting AT+CWMODE=3 (i tried by pure luck lol) i’m back to normal… :slight_smile:

Cheers,
Jay.

1 Like

New Firmware released (1.0.1 b1) - ESP8266_NONOS_SDK_V1.0.1_b1_15_04_02 - ESP8266 Developer Zone

2 Likes

Careful … requires a different (1024K) flash chip because of larger AT commands.
If you want to keep the 512K chip, you’ll need to use the AT file from 1.0.0 - if that works.

Yep that new AT won’t work on most modules :frowning:

tried it on ESP-3 and it didn’t work :(, meaning the AT firmware… the SDK can be used just fine, just flash the AT v0.22 instead of the v0.23

From the ESP forum…

You can still use modules with 512k flash, you just cannot update via cloud.

just set flash downloader to
boot_v1.3+.bin 0x00000
user1.1024.new.bin 0x01000
blank.bin 0x7e000

only the above 3 lines are checked and do not set one for 0xfe000
I kept my flash setting to 4mbit.

this is the firmware version I get after the update
AT+GMR

AT version:0.23.b1.0(Apr 2 2015 23:27:52)
SDK version:1.0.1(b1)
compile time:Apr 2 2015 23:39:06

OK

@ Jay Jay - Did Ctrl Alt Del fix it? :whistle:

lol, nope just the DEL on it’s own this time :slight_smile:

New firmware, v1.0.1 b2!

http://bbs.espressif.com/viewtopic.php?f=5&t=346

If only I had a module to test it with… :whistle:

The b1 update suggested it required the device to have a flash size of 1024KB or higher. That would appear to not be an explicit requirement for the b2 update.

Can anyone tell me how to check if my device(s) are equipped to handle the b1/b2 update?
Does the b2 update require 1024KB or more of flash?
Do the different models of ESP have different memory, e.g. ESP03 has a different amount of memory to the ESP07, etc?

Thanks.

just update as you normally do, the required for the higher memory is for the CLOUD Update… you just won’t get that feature in the smaller sized chip.

1 Like