Tuya Sandwich Evaluation Kit ZigBee Arduino Five-way Lantern

Last Updated on2020-02-13 07:39:2358

Overview

This article is based on the Arduino Nucleo development board, making an RGBCW dimming light connected to the Tuya cloud via ZigBee. Arduino is the most popular open source hardware in the world. It is also an excellent hardware development platform, and it is also the trend of hardware development. Arduino’s simple development method makes developers pay more attention to creativity and implementation. Complete your own project development faster, which greatly saves the cost of learning and shortens the development cycle. On the Arduino Nucleo development board, developers can define various functions by themselves and access the Tuya cloud platform through the ZigBee module.
Terms

Materials

Hardware (4)Software (3) Others (3)
  • Tuya Sandwich ZigBee MCU(TYZS13) Board

    Count:1

  • Arduino Nucleo Development Board

    Count:1

  • Arduino UNO development board

    Count:1

  • Tuya Sandwich (PWM + IIC) Lighting Board

    Count:1

Steps

  • Step 1: Create Product

    Login Tuya Smart Platform to create products

    image-20191205181555478

    Select the product, Tuya can provide customized product development and Soc product online development. There are two intelligent modes for product development. Arduino is developed for MCU connection. Here, select “Lighting” in “Custom” under “Lighting”.

    image-20191205181739825

    Fill in the product information. In “Product Name”, you can name it according to your needs. “Product Model” supports customer customization. “Communication Type” selects “ZigBee”.

    img

    Select the product function, select the product function according to the actual situation, you can select all, or you can add or cancel it individually, and then click “Add selected function”. If the function is not clear for a while, it doesn’t matter, you can edit it again after the creation is complete, you can also add functions and enable the required cloud functions. Custom product function description The demo examples use “switch”, “mode”, “brightness value”, “cooling value”, “color light” "These five DP points.

    image-20191205182715917

    After the selection is completed, the selected DP function point will be displayed, and you can also edit it twice.

    image-20191205182923517

    Choose the style of the App interface and the style of the App control interface. Tuya provides a lot of modules. You can choose freely according to your preferences. Select the app interface, click “Use selected template”, and click Next to enter the following interface.

    image-20191205183301250

    When the webpage jumps here, it means that the app has chosen to complete.

    image-20191205191216652

    Enter the hardware debugging. In the hardware debugging, you need to select the corresponding ZigBee module model, select the “module general firmware solution”, you need to click “MCU SDK one-click package download MCU development package”.

    image-20191205192001648

    image-20191205192201945

    After successful download, you will get a “DevelopResourcePack_Arduino_RGBCW_20191205.zip” compression package. After decompression, you will get mcu_sdk_Arduino_RGBCW_20191205, which contains mcu sdk files, which needs to be ported to Arduino. protocol_Arduino

    _RGBCW_20191205.pdf is the protocol document used by the mcu docking. The readme.txt file briefly introduces the contents of the compressed package. Debugfile

    _Arduino _RGBCW_20191205.json This jison file is the configuration file of the host computer used for mcu docking. The host computer software is stored in

    TuYaCloudSerialPortHelper_Arduino_RGBCW_20191205.zip package needs to be unzipped and installed.

    image-20191205193052560

    Then there is the “extended function” selection, and specific functions can be selected as required.

    ![image-20191205194936361](https://airtake-public-data.oss-cn-hangzhou.aliyuncs.com/fe-static / tuya-docs / db2d7c4a-7688-40e9-95ba-309574fdbc0a.png)

    Then enter the “mass production” stage

    image-20191205195201609

  • Step 2: Arduino Program Development

    Setting up Arduino development environment

    Install Arduino IDE. After the installation is complete, you need to add an additional development board manager URL in the preferences at https://github.com/ stm32duino / BoardManagerFiles / raw / master / STM32 / package_stm_index.json

    image-20191205200544034

    Then you need to add the library corresponding to the nucleo development board, click Tools-> Development board-> Enter STM according to the contribution in the development board manager, and install the corresponding library.

    image-20191205200846058

    image-20191205201044245

    Install STlink driver, used by the development board ** micro usb ** is the data line, select ** STSW-LINK009 **.

    image-20191205201547212

    After the installation is complete, plug in the nucleo development board and check the COM port shown in the figure below in the computer explorer, indicating that the driver installation was successful.

    image-20191205201818252

    Configure in the tool as shown below.

    image-20191205201338783

    Before you start programming, you need to install [STM32CubeProgrammer] ([https://my.st.com/content/my_st_com/en/search.html#q=STM32CubeProgrammer-t=tools-page=1) software. After the installation is complete, you need to configure the environment variables, as shown in the following figure. The environment variables need to be selected according to the installation path of the STM32CubeProgrammer.

    image-20191205202201473

    Arduino program migration, you can refer to Muya MCU SDK Migration Instruction Document.

    Open ArduinoIDE to create a new project and save it.

    image-20191205211056052

    At this time, there are two functions in the project, setup (), which are usually used for initialization and executed only once. The loop () function will be executed in a loop. Find all the following .C and .H files in the MCU development kit and copy these to the newly created Arduino project Directory at the same level and change the suffix **. C ** to **. CPP **. As shown in the figure below, reopen the sketch_dec04a.ino file, and other files in the directory will be automatically loaded.

    image-20191205211224023

    Due to the differences between the migrated file and Arduino, you need to modify the file a little.

    Modify protocol.cpp and system.cpp to remove const

    image-20191205211645962

    The macros such as TRUE, FALSE … in ZigBee.h have been defined. We have changed it to TRUE_, FALSE_

    img

    Comment out all # error… with //

    image-20191205212030183

    setup () function and loop () function modification

    Before modifying, check the nucleo development board Schematic diagram, as shown in the figure below, where CN5, CN6, CN8, CN9, corresponding to the Arduino board plug-in, pay attention to the The definition of IO port is according to the pin number of Arduino UNO. For example, RX corresponds to 0 of the Arduino UNO IO port. For the definition of the IO port in the library of STM32, you can use the serial number such as digitalWrite (13, HIGH);, or you can use the definition of the IO port of STM32, such as digita

    lWrite (PA5, HIGH);

    image-20191206090128454

    img

    #include <SoftwareSerial.h>
    #include "iic.h"
    #include "ZigBee.h"
    
    #define led_w 9
    #define led_c 5
    #define TX_ 1
    #define RX_ 0
    #define DEBUG
    
    #define USER_BUTTON_PIN PC13
    #define USER_LED_PIN PA5
    
    SoftwareSerial mySerial (RX_, TX_);
    
    int time_cnt = 0, cnt = 0, init_flag = 0;
    
    void setup () {
      Serial.begin (115200);
      pinMode (USER_BUTTON_PIN, INPUT); // button pin mode init
      pinMode (USER_LED_PIN, OUTPUT); // led pin mode init
      digitalWrite (PA5, HIGH);
      mySerial.begin (9600); // serial init
      mySerial.println ("myserial init successful!");
      Serial.begin (115200); // PA3 RX PA2 TX
      Serial.println ("serial init successful! \ R \ n");
    
      IIC_Init ();
      delay (10);
      rgb_init (0, 0, 0);
      ZigBee_protocol_init ();
    }
    
    void loop () {
      if (init_flag == 0) {
        time_cnt ++;
        if (time_cnt% 5000 == 0) {
          time_cnt = 0;
          cnt ++;
        }
        ZigBee_stat_led (& cnt); // jion network state led indicator
      }
      
      ZigBee_uart_service ();
      myserialEvent ();
      key_scan ();
    }
    
    void key_scan (void)
    {
      static char ap_ez_change = 0;
      unsigned char buttonState = HIGH;
      buttonState = digitalRead (USER_BUTTON_PIN);
      if (buttonState == LOW) {
        delay (5000);
        if (buttonState == LOW) {
          #ifdef DEBUG
          Serial.println ("mcu send ZigBee jion cmd! \ R \ n");
          #endif
          mcu_network_start ();
          }
          analogWrite (led_w, 0);
          analogWrite (led_c, 0);
          rgb_init (0, 0, 0);
        }
    }
    
    void myserialEvent () {
      if (mySerial.available ()) {
        unsigned char ch = (unsigned char) mySerial.read ();
        uart_receive_input (ch);
      }
    }
    
    void ZigBee_stat_led (int * cnt)
    {
      switch (mcu_get_ZigBee_work_state ())
      {
        case JOINING: // 0x00
          init_flag = 0;
          if (* cnt == 2) {
            * cnt = 0;
          }
          if (* cnt% 2 == 0) // LED BLINK
          {
            analogWrite (led_w, 1);
          }
          else
          {
            analogWrite (led_w, 0);
          }
          break;
        case JOINED:
            analogWrite (led_w, 1);
          break;
        case JOIN_INIT:
          analogWrite (led_w, 0);
          break;
        default:
          analogWrite (led_w, 0);
          break;
      }
    }
    

    In the protocol.cpp file, add the serial port sending function for Arduino platform to the serial port sending function.

    / ************************************************* ****************************
    Function Name: uart_transmit_output
    Function description: Send data processing
    Input parameter: value: Byte data received by serial port
    Return parameter: None
    Instructions for use: Please fill the MCU serial port sending function into this function, and pass the received data as parameters into the serial port sending function
    ********************************************** *************************** /
    extern unsigned char emberSerialWriteByte (unsigned char port, unsigned char dataByte);
    void uart_transmit_output (unsigned char value)
    {
    // # error "Please fill in the MCU serial port sending function and delete the line"
    / *
      // Example:
      extern void Uart_PutChar (unsigned char value);
      Uart_PutChar (value); // Serial port sending function
    * /
    }
    

    Add content as

    #include <SoftwareSerial.h>
    
     extern SoftwareSerial mySerial;
     mySerial.write (value);
    

    Dimming is implemented. The serial port receives data. The process is as follows. First, each byte of the serial port is received in the myserialEvent in the loop function, and then the received data is saved in the uart_receive_input function, and then the data is received through the ZigBee_uart_service function. The data in the array is parsed according to the frame format. If the frame is valid, the data_handle function will be called to process the data according to the command. In this function, the function that processes the DP sent by the ZigBee module is ZigBee_data_point_handle. In the ZigBee_data_point_handle function, the dp_download_handle function is divided according to the content of the DP. Function processing.

    loop ()-> myserialEvent ()-> uart_receive_input (ch)-> ZigBee_uart_service-> data_handle ()-> ZigBee_data_point_handle ()-> dp_download_handle ()
    
    unsigned char dp_download_handle (unsigned char dpid, const unsigned char value [], unsigned short length)
    {
      / *********************************
      Current function processing can be issued / reportable data call
      The specific function needs to implement the issued data processing
      To complete the application, the processing result needs to be fed back to the APP.Otherwise, the APP will consider that the delivery fails.
      *********************************** /
      unsigned char ret = 0;
      switch (dpid)
      {
        case DPID_SWITCH_LED:
          // Switch processing function
          ret = dp_download_switch_led_handle (value, length);
          break;
        case DPID_WORK_MODE:
          // pattern processing function
          ret = dp_download_work_mode_handle (value, length);
          break;
        case DPID_BRIGHT_VALUE:
          // Brightness value processing function
          ret = dp_download_bright_value_handle (value, length);
          break;
        case DPID_TEMP_VALUE:
          // Cold and warm value processing function
          ret = dp_download_temp_value_handle (value, length);
          break;
        case DPID_COLOUR_DATA:
          // Color light processing function
          ret = dp_download_colour_data_handle (value, length);
          break;
    
      default:
        break;
      }
      return ret;
    }
    

    The DP processing function in the dp_download_handle function is automatically generated, but the specific implementation is determined by the developer. The implementation of this demo is shown below.

    Added in dp_download_switch_led_handle function

      if (switch_led == 0)
      {
        // Switch off
        analogWrite (led_w, 0);
        analogWrite (led_c, 0);
        rgb_init (0, 0, 0);
      }
      else
      {
        // Switch on
        if (work_mode == 0)
        {
          analogWrite (led_w, pre_bri);
          analogWrite (led_c, pre_temp);
          rgb_init (0,0,0);
        }
        else
        {
          analogWrite (led_w, 0);
          analogWrite (led_c, 0);
         rgb_init (mcu_default_color.red, mcu_default_color.green, mcu_default_color.blue);
        }
      }
    

    Add in dp_download_work_mode_handle function

        case 0:
          work_mode = 0;
          rgb_init (0, 0, 0);
          analogWrite (led_w, pre_bri);
          analogWrite (led_c, pre_temp);
          break;
          
        case 1:
          work_mode = 1;
          analogWrite (led_w, 0);
          analogWrite (led_c, 0);
          rgb_init (mcu_default_color.red, mcu_default_color.green, mcu_default_color.blue);
          break;
    

    Add in dp_download_bright_value_handle function

      default_brig_value = bright_value;
      if (default_brig_value == 10) {
        default_brig_value = 0;
      }
      / *
      // VALUE type data processing
      
      * /
      warm = (float) default_brig_value / 4.0 * ((float) default_temp_value / 1000.0);
      white = (float) default_brig_value / 4.0-warm;
      // printf ("2. warm =% d, white =% d \ r \ n", warm, white);
      pre_bri = white;
      pre_temp = warm;
    
    
    

    Add in dp_download_temp_value_handle function

      default_temp_value = temp_value;
      work_mode = 0;
      / *
      // VALUE type data processing
      
      * /
      warm = (float) default_brig_value / 4.0 * ((float) default_temp_value / 1000.0);
      white = (float) default_brig_value / 4.0-warm;
      // printf ("2. warm =% d, white =% d \ r \ n", warm, white);
      pre_bri = white;
      pre_temp = warm;
      analogWrite (led_w, white);
      analogWrite (led_c, warm);
    
    
    

    Added in dp_download_colour_data_handle

      unsigned char string_data [12];
      unsignedshort h, s, v;
      unsigned short r, g, b;
      work_mode = 1;
      string_data [0] = value [0];
      string_data [1] = value [1];
      string_data [2] = value [2];
      string_data [3] = value [3];
      string_data [4] = value [4];
      string_data [5] = value [5];
      string_data [6] = value [6];
      string_data [7] = value [7];
      string_data [8] = value [8];
      string_data [9] = value [9];
      string_data [10] = value [10];
      string_data [11] = value [11];
    
      h = __str2short (__ asc2hex (string_data [0]), __asc2hex (string_data [1]), __asc2hex (string_data [2]), __asc2hex (string_data [3]));
      s = __ str2short (__ asc2hex (string_data [4]), __asc2hex (string_data [5]), __asc2hex (string_data [6]), __asc2hex (string_data [7]));
      v = __str2short (__ asc2hex (string_data [8]), __asc2hex (string_data [9]), __asc2hex (string_data [10]), __asc2hex (string_data [11]));
      if (v <= 10) {
        v = 0;
      } else {
        v = color_val_lmt_get (v);
      }
      hsv2rgb ((float) h, (float) s / 1000.0, (float) v / 1000.0, & r, & g, & b);
      tuya_light_gamma_adjust (r, g, b, & mcu_default_color.red, & mcu_default_color.green, & mcu_default_color.blue);
    
      // printf ("r =% d, g =% d, b =% d \ r \ n", mcu_default_color.red, mcu_default_color.green, mcu_default_color.blue);
      rgb_init (mcu_default_color.red, mcu_default_color.green, mcu_default_color.blue);
    
    
    

    In the protocol.cpp file, you need to add some content to achieve dimming.

    #include <SoftwareSerial.h>
    #include "iic.h"
    
    #define led_w 9
    #define led_c 5
    #define SUCCESS 0
    #define ERROR 1
    struct default_color {
      unsigned char red;
      unsigned char green;
      unsigned char blue;
    };
    
    struct default_color mcu_default_color = {0};
    unsigned short default_brig_value = 0, pre_bri = 0;
    unsigned short default_temp_value = 0, pre_temp = 0;
    uint8_t work_mode = 0;
    
    unsigned char gamma_red [] = {
      0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13, 13,
      14, 15, 15, 16, 17, 18, 18, 19, 20, 21, 21, 22, 23, 24, 24, 25, 26, 27, 28,
      28, 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44,
      44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
      62, 63, 64, 65, 66, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
      80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
      99, 100, 101, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
      115, 116, 117, 118, 119, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
      131, 132, 134, 135, 136, 137, 138, 139, 140, 141, 142, 144, 145, 146, 147,
      148, 149, 150, 151, 152, 154, 155, 156, 157, 158, 159, 160, 162, 163, 164,
      165, 166, 167, 168, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181,
      182, 184, 185, 186, 187, 188, 189, 191, 192, 193, 194, 195, 196, 198, 199,
      200, 201, 202, 204, 205, 206, 207, 208, 210, 211, 212, 213, 214, 216, 217,
      218, 219, 220, 222, 223, 224, 225, 227, 228, 229, 230, 231, 233, 234, 235,
      236, 238, 239, 240, 241, 243, 244, 245, 246, 248, 249, 250, 251, 253, 254, 255
    };
    
    
    // GREEN 0.6-70%
    unsigned char gamma_green [] = {
      0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4,
      4, 5, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12,
      13, 13, 13, 14, 14, 15, 15, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21,
      21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 29, 29, 30, 30, 31,
      31, 32, 33, 33, 34, 34, 35, 36, 36, 37, 38, 38, 39, 39, 40, 41, 41, 42, 43,
      43, 44, 45, 45, 46, 47, 47, 48, 49, 49, 50, 51, 52, 52, 53, 54, 54, 55, 56,
      57, 57, 58, 59, 60, 60, 61, 62, 63, 63, 64, 65, 66, 66, 67, 68, 69, 70, 70,
      71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 80, 81, 82, 83, 84, 85, 86, 86,
      87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
      104, 105, 106, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
      118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
      133, 134, 135, 136, 137, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
      149, 150, 151, 152, 154, 155, 156, 157, 158, 159, 160, 161, 162, 164, 165,
      166, 167, 168, 169, 170, 172, 173, 174, 175, 176, 177, 179
    };
    
    
    // BLUE 0.6-75%
    unsigned char gamma_blue [] = {
      0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 5,
      5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13,
      14, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
      23, 23, 24, 24, 25, 25, 26, 27, 27, 28, 28, 29, 29, 30, 31, 31, 32, 32, 33,
      34, 34, 35, 36, 36, 37, 38, 38, 39, 40, 40, 41, 42, 42, 43, 44, 44, 45, 46,
      46, 47, 48, 49, 49, 50, 51, 51, 52, 53, 54, 54, 55, 56, 57, 58, 58, 59, 60,
      61, 61, 62, 63, 64, 65, 65, 66, 67, 68, 69, 70, 70, 71, 72, 73, 74, 75, 76,
      76, 77, 78, 79, 80, 81, 82, 83, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
      94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
      109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
      123, 124, 125, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
      138, 139, 141, 142, 143, 144, 145, 146, 147, 148, 150, 151, 152, 153,
      154, 155, 156, 158, 159, 160, 161, 162, 163, 165, 166, 167, 168, 169,
      170, 172, 173, 174, 175, 176, 178, 179, 180, 181, 183, 184, 185, 186,
      188, 189, 190, 191
    };
    
    unsigned int __str2short (unsigned int a, unsigned int b, unsigned int c, unsigned int d)
    {
      return (a << 12) | (b << 8) | (c << 4) | (d & 0xf);
    }
    unsigned char __asc2hex (unsigned char asccode)
    {
      unsigned char ret;
    
      if ('0' <= asccode && asccode <= '9')
        ret = asccode-'0';
      else if ('a' <= asccode && asccode <= 'f')
        ret = asccode-'a' + 10;
      else if ('A' <= asccode && asccode <= 'F')
        ret = asccode-'A' + 10;
      else
        ret = 0;
    
      return ret;
    }
    
    unsigned short color_val_lmt_get (unsigned short dp_val)
    {
      unsigned short max = 255 * 100/100;
      unsigned short min = 255 * 1/100;
    
      return ((dp_val-10) * (max-min) / (1000-10) + min);
    }
    void hsv2rgb (float h, float s, float v, unsigned short * color_r, unsigned short * color_g, unsigned short * color_b)
    {
      float h60, f;
      unsigned int h60f, hi;
    
      h60 = h / 60.0;
      h60f = h / 60;
    
      hi = (int) h60f% 6;
      f = h60-h60f;
    
      float p, q, t;
    
      p = v * (1-s);
      q = v * (1-f * s);
      t = v * (1-(1-f) * s);
    
      float r, g, b;
    
      r = g = b = 0;
      if (hi == 0) {
        r = v; g = t; b = p;
      } else if (hi == 1) {
        r = q; g = v; b = p;
      } else if (hi == 2) {
        r = p; g = v; b = t;
      } else if (hi == 3) {
        r = p; g = q; b = v;
      } else if (hi == 4) {
        r = t; g = p; b = v;
      } else if (hi == 5) {
        r = v; g = p; b = q;
      }
    
      r = (r * (float) 500);
      g = (g * (float) 500);
      b = (b * (float) 500);
    
      r * = 100;
      g * = 100;
      b * = 100;
    
      * color_r = (r + 50) / 100;
      * color_g = (g + 50) / 100;
      * color_b = (b + 50) / 100;
    }
    void tuya_light_gamma_adjust (unsigned short red, unsigned short green, unsigned short blue, unsigned char * adjust_red, unsigned char * adjust_green, unsigned char * adjust_blue)
    {
    
      * adjust_red = gamma_red [red * 255/500] * 500/255;
      * adjust_green = gamma_green [green * 255/500] * 500/255;
      * adjust_blue = gamma_blue [blue * 255/500] * 500/255;
    }
    
    
    

    Because the data sent by the DP of the colorful light is the hsv model, it needs to be converted into specific RGB values. At the same time, the RGBCW lamp board uses I2C to drive RGB LEDs and PWM to drive CW dimming. The contents of IIC.h and IIC.c ​​files are shown below and need to be added to the entire program.

    #ifndef IIC_H
    #define IIC_H
    #include "Arduino.h"
    
    #define IIC_SCL 15
    #define IIC_SDA_OUT 14
    #define IIC_SDA_IN 14
    
    #define READ_SDA_IN digitalRead (IIC_SDA_IN)
    #define IIC_INPUT_MODE_SET () pinMode (IIC_SDA_IN, INPUT)
    #define IIC_OUTPUT_MODE_SET () pinMode (IIC_SDA_OUT, OUTPUT)
    
    void IIC_Init (void);
    void IIC_START (void);
    void IIC_STOP (void);
    unsigned char IIC_GetACK (void);
    void IIC_SendAck (unsigned char ack);
    void IIC_WriteOneByte (unsigned char data);
    void IIC_WriteOneBit (bool data);
    unsigned char IIC_ReadOneByte (void);
    void rgb_init (unsigned char red, unsigned char green, unsigned char blue);
    #endif
    
    
    
    #include "iic.h"
    
    void IIC_Init (void)
    {
      pinMode (IIC_SCL, OUTPUT);
      pinMode (IIC_SDA_OUT, OUTPUT);
      digitalWrite (IIC_SCL, HIGH);
      digitalWrite (IIC_SDA_OUT, HIGH);
    }
    void IIC_START (void)
    {
      IIC_OUTPUT_MODE_SET ();
      digitalWrite (IIC_SCL, HIGH);
      digitalWrite (IIC_SDA_OUT, HIGH);
      delayMicroseconds (2);
      digitalWrite (IIC_SDA_OUT, LOW);
      delayMicroseconds (2);
      digitalWrite (IIC_SCL, LOW);
    }
    void IIC_STOP (void)
    {
      IIC_OUTPUT_MODE_SET ();
      digitalWrite (IIC_SCL, LOW);
      digitalWrite (IIC_SDA_OUT, LOW);
      delayMicroseconds (2);
      digitalWrite (IIC_SCL, HIGH);
      delayMicroseconds (2);
      digitalWrite (IIC_SDA_OUT, HIGH);
    }
    unsigned char IIC_GetACK (void)
    {
      unsigned char cnt = 0;
      IIC_INPUT_MODE_SET ();
      digitalWrite (IIC_SDA_OUT, HIGH);
    
      digitalWrite (IIC_SCL, LOW);
      delayMicroseconds (2);
      digitalWrite (IIC_SCL, HIGH);
    
      while (READ_SDA_IN)
      {
        cnt ++;
        delayMicroseconds (1);
        if (cnt> = 250) return 1;
      }
      digitalWrite (IIC_SCL, LOW);
      return 0;
    }
    void IIC_SendAck (unsigned char ack)
    {
      IIC_OUTPUT_MODE_SET ();
      digitalWrite (IIC_SCL, LOW);
      if (ack) digitalWrite (IIC_SDA_OUT, HIGH);
      else digitalWrite (IIC_SDA_OUT, LOW);
      delayMicroseconds (2);
      digitalWrite (IIC_SCL, HIGH);
      delayMicroseconds (2);
      digitalWrite (IIC_SCL, LOW);
    }
    void IIC_WriteOneByte (unsigned char data)
    {
      unsigned char i;
      IIC_OUTPUT_MODE_SET ();
      for (i = 0; i <8; i ++)
      {
        digitalWrite (IIC_SCL, LOW);
        if (data & 0x80) digitalWrite (IIC_SDA_OUT, HIGH);
        else digitalWrite (IIC_SDA_OUT, LOW);
        delayMicroseconds (2);
        digitalWrite (IIC_SCL, HIGH);
        delayMicroseconds (2);
        data << = 1;
      }
      digitalWrite (IIC_SCL, LOW);
    }
    void IIC_WriteOneBit (bool data)
    {
      IIC_OUTPUT_MODE_SET ();
      digitalWrite (IIC_SCL, LOW);
    
      if (data) digitalWrite (IIC_SDA_OUT, HIGH);
      else digitalWrite (IIC_SDA_OUT, LOW);
    
      delayMicroseconds (2);
      digitalWrite (IIC_SCL, HIGH);
      delayMicroseconds (2);
    }
    unsigned char IIC_ReadOneByte (void)
    {
      unsigned char data = 0, i = 0;
      IIC_INPUT_MODE_SET ();
      for (i = 0; i <8; i ++)
      {
        digitalWrite (IIC_SCL, LOW);
        delayMicroseconds (2);
        digitalWrite (IIC_SCL, HIGH);
        data << = 1;
        if (IIC_SDA_IN) data | = 0x01;
        delayMicroseconds (2);
      }
      digitalWrite (IIC_SCL, LOW);
      return data;
    }
    void rgb_init (unsigned char red, unsigned char green, unsigned char blue)
    {
      IIC_START ();
      IIC_WriteOneByte (0x00);
      IIC_WriteOneByte (0x00);
      IIC_WriteOneByte (0x00);
      IIC_WriteOneByte (0x00);
      IIC_WriteOneByte (0x00);
      IIC_WriteOneByte (0x00);
      IIC_WriteOneBit (true);
      IIC_WriteOneByte (red);
      IIC_WriteOneByte (green);
      IIC_WriteOneByte (blue);
      IIC_STOP ();
    }
    
    
    

    Download to the development board, it indicates that the download is successful.

    image-20191205221842049

    Press the button for 5 seconds to perform the network configuration operation. You need to open the gateway’s network configuration.

    image-20191205222405049

    image-20191205222606556

  • Step 3: Debugging effect

    image-20191205223112617