Project tutorial
My FAN ARM (control servo with WiFi)

My FAN ARM (control servo with WiFi) © GPL3+

With both WiFi module on mbed platform, controlling servo & dc motor in UDP

  • 2,989 views
  • 0 comments
  • 4 respects

Components and supplies

About this project

Hello everyone!

Today, I did it my own FAN ARM.

I can control the eagle freely and can turn on and off the FAN. (actually I need to add Fan on the DC motor)

It is controlled by joystick and push button with WiFi.

So, above all, I can control the FAN ARM wherever I am and wherever I want!

Now, I start to talk about the details.

Step 1: Components

The components all come form mbed.com !

1. WIZwiki-W7500 : as MCU. It is mbed platform

2. Two WizFi250 shield : as communication

3. Motor shield : for DC motor voltage and It needs 5V supply.

4. Joystick shield : It is totally optional. I regret to buy it.. you will know next why I did..

5. Two AX-12A : for the arm. It is serial motor. You need to learn to use it.

I add Link to learn more about the components.

WIZwiki-W7500

WizFi250

DC motor

Joystick

AX-12A : You need to install software to set the servo. Please visit http://support.robotis.com/ and Download "Dynamixel Wizard"

Step 2: Concept

This is all about the concept of the instructable.

---------------------------------- Client -------------------------------------------------------------

I use a WiFi(left one in the picture) as UDP Client with joystick & push button.

First, it connects AT.

Then Get the analog and digital data from joystick and push button and send it to UDP Server.


------------------------------------- Server -----------------------------------------------------------

I use a WiFi as AT mode and UDP Server with Servo & DC motor.

It always opens and wait for the data from Client.

Right after receiving data, Servo and DC controlled with UART and PWM.

-------------------------------------------------------------------------------------------------------------

Step 3: FAN ARM

FAN ARM has two serial Servo motor and one DC motor.

Two servo make angle and DC turn on/off fan. (As I did before, I didn't put a fan)

Controller can control it with WiFi and the communication protocol is UDP.

Step 4: Hardwired

These are hardwired I did.

I know it is so confusing and look hard..

But I know, It is pretty simple If you will find how to wire between WIZwiki-W7500, mbed platform, and WizFi250.

"Controller" is UDP Client and it sends analog data from joystick and digital data from push buttom to UDP Server.

"FAN ARM" , UDP Server, receives the data from "Controller" and control the Servo and DC motor as I want.

=================================WizFi250===============================

I add Link to learn more about WizFi250.

http://www.life4iot.com/2015/06/30/wizfi250-hello-world-demo-on-wizwiki-w7500-of-mbed-platform/?lang=en

=========================================================================

Last Picture is the back of Joystick shield. And I has the reason why I regret it.

I tried to use joystick with 5V with the PCB.

But it did not give me the data I want.

After I wired with 3.3V, I got the right data.

And.. one more thing, you can not use the push button right away. Caz, the PCB doesn't wired with 3.3V

So, I did it by myself.

Step 5: Why UDP ?

I choose UDP, not TCP. TCP has many rules to send data to Server like sync, ack..

But UDP is simple.

Client just send packet. It doesn't matter to check It is going well or Server can receive.

So, usually, It used that does not want buffering but streaming.

I also do not care about losing the data packet. It is not important data.

If it is missed, I can send once again. So, Server can receive it next time.

Picture shows UDP Server and Client.

UDP server opened with 192.168.100.1 as AT mode; WizFi250_AP_Test.

UDP client opened with 192.168.100.2 and endpoint is 192.168.100.1(WizFi250_AP_Test)

Step 6: DEMO Video

https://www.youtube.com/embed/n_ij739Rzqg

Step 7: Open Source

I uploaded two projects, FAN ARM; UDP Server and Controller; UDP Client

You need to download then to each mbed platform

You can understand what mbed is from here

http://www.instructables.com/id/Your-own-Weather-Forecast-with-WIZwiki-W7500/

Code

FAN ARM UDP ClientC/C++
main.cpp
#include <stdio.h>
#include "mbed.h"
#include "WizFi250Interface.h"
 
#define SERVER_ADDRESS "192.168.100.1"
#define SERVER_PORT    5000
 
#define CLIENT_PORT    3000
 
#define SECURE WizFi250::SEC_AUTO
#define SSID "WizFi250_AP_Test"
#define PASS "1234567890"
 
#if defined(TARGET_WIZwiki_W7500)
    WizFi250Interface wizfi250(D1,D0,D7,D8,PA_12,NC,115200);
    Serial pc(USBTX, USBRX);
#endif
 
AnalogIn xAxis(A0);
AnalogIn yAxis(A1);
 
DigitalIn Fanon(D4);
DigitalIn Fanoff(D3);
 
DigitalOut red(LED1);
DigitalOut green(LED2);
 
void UDPClient();
 
 
int main()
{
    pc.baud(115200);
 
    printf("WizFi250 Hello World demo. \r\n");
    wizfi250.init();
    //wizfi250.setAddress("192.168.100.10","255.255.255.0","192.168.100.1");
    if ( wizfi250.connect(SECURE, SSID, PASS))      return -1;
    printf("IP Address is %s\r\n", wizfi250.getIPAddress());
    
    wait(1.0);
    
    UDPClient();
    
    wizfi250.disconnect();
}
 
 
void UDPClient()
{
    
    UDPSocket client;
    printf("Socket opened\r\n");
    
    client.set_blocking(false);
    client.bind(CLIENT_PORT);
 
    Endpoint server;
    
    server.set_address(SERVER_ADDRESS, SERVER_PORT);
 
    /* ready sign */
    green = 0;
    wait(0.3);
    green = 1;
    wait(0.3);
    green = 0;
    wait(0.3);
    green = 1;
    wait(0.3);
    green = 0;
 
    while(true)
    {
        int x,y;    
    
        char *cmd1 = "left";
        char *cmd2 = "right";
        char *cmd3 = "up";
        char *cmd4 = "down";
        char *cmd5 = "init";
        char *cmd6 = "fanon";
        char *cmd7 = "fanoff";
    
        char send_data[10];
        
        x = xAxis.read() * 1000; // float (0->1) to int (0-1000)
        y = yAxis.read() * 1000;
          
        if ( (x < 10) || ((y > 350)&&(y < 420)) )       
        {
            sprintf(send_data, "%s", cmd1);
            printf("left\r\n");
        }
        else if ( (x > 990) || ((y > 520)&&(y < 620)) )
        {
            sprintf(send_data, "%s", cmd2);
            printf("right\r\n");
        }
        else if ( ((x > 480)&&(x < 570)) || (y > 990) ) 
        {
            sprintf(send_data, "%s", cmd3);
            printf("up\r\n");
        }
        else if ( ((x > 350)&&(x < 420)) || (y < 10) )  
        {
            sprintf(send_data, "%s", cmd4);
            printf("down\r\n");
        }
        else if (Fanon == 1)
        {
            sprintf(send_data, "%s", cmd6);
            printf("fan on\r\n");
        }
        else if (Fanoff == 1)
        {
            sprintf(send_data, "%s", cmd7);
            printf("fan off\r\n");
        }
        else
        {
            sprintf(send_data, "%s", cmd5);
            printf("init\r\n");
        }
 
         
        client.sendTo(server, send_data, sizeof(send_data));
        
        char in_buffer[256];
        int n = client.receiveFrom(server, in_buffer, sizeof(in_buffer));
        in_buffer[n] = '\0';
 
        if( n > 0 )
            printf("%s\r\n", in_buffer);
            
        wait(1.0);
    };
 
    client.close();
}
FAN ARM UDP Server C/C++
main.cpp
#include <stdio.h>
#include "mbed.h"
#include "WizFi250Interface.h"
 
/* AX-12 */
#define AX12_REG_GOAL_POSITION 0x1E
#define AX12_REG_MOVING 0x2E
#define AX_Init 330
 
#define SERVER_PORT    5000
 
#define SECURE WizFi250::SEC_WPA2_MIXED
#define SSID "WizFi250_AP_Test"
#define PASS "1234567890"
 
#if defined(TARGET_WIZwiki_W7500)
    WizFi250Interface wizfi250(D1,D0,D7,D8,PA_12,NC,115200);
    Serial pc(USBTX, USBRX);
#endif
 
PwmOut Fan(D3);
 
DigitalOut red(LED1);
DigitalOut green(LED2);
 
 
void UDPServer();
 
/* AX-12 */
int HeadUD = 200;
int HeadRL = AX_Init;
 
void SetGoal(int ID, int degrees, int flags);
int write(int ID, int start, int bytes, char* data, int flag);
int read(int ID, int start, int bytes, char* data);
int isMoving(int ID);
 
int main()
{
    pc.baud(115200);
 
    printf("WizFi250 Hello World demo. \r\n");
    wizfi250.init();
    wizfi250.setAddress("192.168.100.1","255.255.255.0","192.168.100.1");
    if ( wizfi250.connect(SECURE, SSID, PASS, WizFi250::WM_AP))      return -1;
    printf("IP Address is %s\r\n", wizfi250.getIPAddress());
    
    wait(1.0);
    UDPServer();
    
    wizfi250.disconnect();
}
 
 
void UDPServer(){
    UDPSocket server;
    
    printf("Socket opened\r\n");
    
    server.set_blocking(false);
    server.bind(SERVER_PORT);
    
    printf("port open\r\n");
    
    Endpoint client;
    
    printf("endpoint created");
    
    char buffer[10];
    
    int move1 = AX_Init;
    int move2 = AX_Init;
        
        while(true)
        {
            int n = server.receiveFrom(client, buffer, sizeof(buffer));
            
            if(n > 0)
            {
                //printf("Received packet from: %s\n", client.get_address());
                
                buffer[n] = '\0';
 
                if(strstr(buffer, "down"))
                {   
                    printf("down\r\n");
                    if(move1 >= 800){
                        move1 = move1;
                        SetGoal(8, move1, 1);
                    }else{
                        move1 += 20;
                        SetGoal(8, move1, 1);
                    }
                }
                else if(strstr(buffer, "up"))
                {
                    printf("up\r\n");
                    if(move1 == 200){
                        move1 = move1;
                        SetGoal(8, move1, 1);
                    }else{
                        move1 -= 20;
                        SetGoal(8, move1, 1);
                    }
                }
                else if(strstr(buffer, "left"))
                {
                    printf("left\r\n");   
                    if(move2 >= 800){
                        move2 = move2;
                        SetGoal(16, move2, 1);
                    }else{
                        move2 += 20;
                        SetGoal(16, move2, 1);
                    }
                }
                else if(strstr(buffer, "right"))
                {
                    printf("right\r\n");
                    if(move2 == 200){
                        move2 = move2;
                        SetGoal(16, move2, 1);
                    }else{
                        move2 -= 20;
                        SetGoal(16, move2, 1);
                    }
                }
                else if(strstr(buffer, "init"))
                {
                    printf("init\r\n");
                    move1 = move1;
                    move2 = move2;
                    SetGoal(8, move1, 1);
                    SetGoal(16, move2, 1);
                }
                else if(strstr(buffer, "fanon"))
                {
                    printf("fan on\r\n");
                    Fan.write(0.8);
                }
                else if(strstr(buffer, "fanoff"))    
                {
                    printf("fan off\r\n");
                    Fan.write(0);
                }
            }
        }
}
 
 
void SetGoal(int ID, int degrees, int flags) {
 
    char reg_flag = 0;
    char data[2];
 
    // set the flag is only the register bit is set in the flag
    if (flags == 0x2) {
        reg_flag = 1;
    }
 
    // 1023 / 300 * degrees
    int goal = degrees;
    //short goal = (1023 * degrees) / 300;
 
    data[0] = goal & 0xff; // bottom 8 bits
    data[1] = goal >> 8;   // top 8 bits
 
    // write the packet, return the error code
    write(ID, AX12_REG_GOAL_POSITION, 2, data, reg_flag);
    
    if (flags == 1) {
    // block until it comes to a halt
    
        while (isMoving(ID)) {}
    }
}
 
int write(int ID, int start, int bytes, char* data, int flag) {
// 0xff, 0xff, ID, Length, Intruction(write), Address, Param(s), Checksum
 
    char TxBuf[16];
    char sum = 0;
    char Status[6];
 
#ifdef AX12_WRITE_DEBUG
    pc.printf("\nwrite(%d,0x%x,%d,data,%d)\n",ID,start,bytes,flag);
#endif
 
    // Build the TxPacket first in RAM, then we'll send in one go
#ifdef AX12_WRITE_DEBUG
    pc.printf("\nInstruction Packet\n  Header : 0xFF, 0xFF\n");
#endif
 
    TxBuf[0] = 0xff;
    TxBuf[1] = 0xff;
 
    // ID
    TxBuf[2] = ID;
    sum += TxBuf[2];
 
#ifdef AX12_WRITE_DEBUG
    pc.printf("  ID : %d\n",TxBuf[2]);
#endif
 
    // packet Length
    TxBuf[3] = 3+bytes;
    sum += TxBuf[3];
 
#ifdef AX12_WRITE_DEBUG
    pc.printf("  Length : %d\n",TxBuf[3]);
#endif
 
    // Instruction
    if (flag == 1) {
        TxBuf[4]=0x04;
        sum += TxBuf[4];
    } else {
        TxBuf[4]=0x03;
        sum += TxBuf[4];
    }
 
#ifdef AX12_WRITE_DEBUG
    pc.printf("  Instruction : 0x%x\n",TxBuf[4]);
#endif
 
    // Start Address
    TxBuf[5] = start;
    sum += TxBuf[5];
 
#ifdef AX12_WRITE_DEBUG
    pc.printf("  Start : 0x%x\n",TxBuf[5]);
#endif
 
    // data
    for (char i=0; i<bytes ; i++) {
        TxBuf[6+i] = data[i];
        sum += TxBuf[6+i];
 
#ifdef AX12_WRITE_DEBUG
        pc.printf("  Data : 0x%x\n",TxBuf[6+i]);
#endif
 
    }
 
    // checksum
    TxBuf[6+bytes] = 0xFF - sum;
 
#ifdef AX12_WRITE_DEBUG
    pc.printf("  Checksum : 0x%x\n",TxBuf[6+bytes]);
#endif
 
    // Transmit the packet in one burst with no pausing
    for (int i = 0; i < (7 + bytes) ; i++) {
        pc.putc(TxBuf[i]);
    }
        // Wait for the bytes to be transmitted
    wait (0.00002);
 
    // Skip if the read was to the broadcast address
    if (ID != 0xFE) {
 
        // response packet is always 6 + bytes
        // 0xFF, 0xFF, ID, Length Error, Param(s) Checksum
        // timeout is a little more than the time to transmit
        // the packet back, i.e. (6+bytes)*10 bit periods
 
        int timeout = 0;
        int plen = 0;
        while ((timeout < ((6+bytes)*10)) && (plen<(6+bytes))) {
 
            if (pc.readable()) {
                Status[plen] = pc.getc();
                plen++;
                timeout = 0;
            }
 
            // wait for the bit period
            wait (1.0/9600);
            timeout++;
        }
 
        if (timeout == ((6+bytes)*10) ) {
            return(-1);
        }
 
        // Copy the data from Status into data for return
        for (int i=0; i < Status[3]-2 ; i++) {
            data[i] = Status[5+i];
        }
 
#ifdef AX12_READ_DEBUG
        printf("\nStatus Packet\n");
        printf("  Header : 0x%x\n",Status[0]);
        printf("  Header : 0x%x\n",Status[1]);
        printf("  ID : 0x%x\n",Status[2]);
        printf("  Length : 0x%x\n",Status[3]);
        printf("  Error Code : 0x%x\n",Status[4]);
 
        for (int i=0; i < Status[3]-2 ; i++) {
            printf("  Data : 0x%x\n",Status[5+i]);
        }
 
        printf("  Checksum : 0x%x\n",Status[5+(Status[3]-2)]);
#endif
 
    } // if (ID!=0xFE)
 
    return(Status[4]);
}
 
int read(int ID, int start, int bytes, char* data) {
 
    char PacketLength = 0x4;
    char TxBuf[16];
    char sum = 0;
    char Status[16];
 
    Status[4] = 0xFE; // return code
 
#ifdef AX12_READ_DEBUG
    printf("\nread(%d,0x%x,%d,data)\n",ID,start,bytes);
#endif
 
    // Build the TxPacket first in RAM, then we'll send in one go
#ifdef AX12_READ_DEBUG
    printf("\nInstruction Packet\n  Header : 0xFF, 0xFF\n");
#endif
 
    TxBuf[0] = 0xff;
    TxBuf[1] = 0xff;
 
    // ID
    TxBuf[2] = ID;
    sum += TxBuf[2];
 
#ifdef AX12_READ_DEBUG
    printf("  ID : %d\n",TxBuf[2]);
#endif
 
    // Packet Length
    TxBuf[3] = PacketLength;    // Length = 4 ; 2 + 1 (start) = 1 (bytes)
    sum += TxBuf[3];            // Accululate the packet sum
 
#ifdef AX12_READ_DEBUG
    printf("  Length : 0x%x\n",TxBuf[3]);
#endif
 
    // Instruction - Read
    TxBuf[4] = 0x2;
    sum += TxBuf[4];
 
#ifdef AX12_READ_DEBUG
    printf("  Instruction : 0x%x\n",TxBuf[4]);
#endif
 
    // Start Address
    TxBuf[5] = start;
    sum += TxBuf[5];
 
#ifdef AX12_READ_DEBUG
    printf("  Start Address : 0x%x\n",TxBuf[5]);
#endif
 
    // Bytes to read
    TxBuf[6] = bytes;
    sum += TxBuf[6];
 
#ifdef AX12_READ_DEBUG
    printf("  No bytes : 0x%x\n",TxBuf[6]);
#endif
 
    // Checksum
    TxBuf[7] = 0xFF - sum;
#ifdef AX12_READ_DEBUG
    printf("  Checksum : 0x%x\n",TxBuf[7]);
#endif
 
    // Transmit the packet in one burst with no pausing
    for (int i = 0; i<8 ; i++) {
        pc.putc(TxBuf[i]);
    }
 
    // Wait for the bytes to be transmitted
    wait (0.00002);
 
    // Skip if the read was to the broadcast address
    if (ID != 0xFE) {
 
 
 
        // response packet is always 6 + bytes
        // 0xFF, 0xFF, ID, Length Error, Param(s) Checksum
        // timeout is a little more than the time to transmit
        // the packet back, i.e. (6+bytes)*10 bit periods
 
        int timeout = 0;
        int plen = 0;
        while ((timeout < ((6+bytes)*10)) && (plen<(6+bytes))) {
 
            if (pc.readable()) {
                Status[plen] = pc.getc();
                plen++;
                timeout = 0;
            }
 
            // wait for the bit period
            wait (1.0/9600);
            timeout++;
        }
 
        if (timeout == ((6+bytes)*10) ) {
            return(-1);
        }
 
        // Copy the data from Status into data for return
        for (int i=0; i < Status[3]-2 ; i++) {
            data[i] = Status[5+i];
        }
 
#ifdef AX12_READ_DEBUG
        printf("\nStatus Packet\n");
        printf("  Header : 0x%x\n",Status[0]);
        printf("  Header : 0x%x\n",Status[1]);
        printf("  ID : 0x%x\n",Status[2]);
        printf("  Length : 0x%x\n",Status[3]);
        printf("  Error Code : 0x%x\n",Status[4]);
 
        for (int i=0; i < Status[3]-2 ; i++) {
            printf("  Data : 0x%x\n",Status[5+i]);
        }
 
        printf("  Checksum : 0x%x\n",Status[5+(Status[3]-2)]);
#endif
 
    } // if (ID!=0xFE)
 
    return(Status[4]);
}
 
int isMoving(int ID) {
 
    char data[1];
    read(ID,AX12_REG_MOVING,1,data);
    return(data[0]);
}

Schematics

controller schematic
This is controller part
Controller
FAN ARM body
This part is FAN ARM body
Fan%20arm%20body

Comments

Similar projects you might like

Just make it!! BT Smart Fan :)

Project tutorial by Justin Kim

  • 3,477 views
  • 3 comments
  • 13 respects

Servo Control with TV Remote Control

Project showcase by eldo85

  • 13,025 views
  • 6 comments
  • 35 respects

All About Servo Motors and Servo Motor Tester

Project tutorial by RoboCircuits

  • 4,440 views
  • 1 comment
  • 11 respects

Arduino WiFi Robot Control Using Mobile Phone

Project tutorial by Jithin Sanal

  • 4,833 views
  • 0 comments
  • 19 respects
Add projectSign up / Login