2015. 12. 21. 18:58

LEGO Wall-E Motorized


LEGO Wall-E Motorized using Arduino

controlling by iPhone


기말고사 기간에 레고 월E 출시 발견. 이어서, 마인드스톰 추가 구성해서 움직이게 한거 보고 넋이 나감. 

그래서 겨울 방학때 아래의 미션하에 프로젝트를 진행하였다:


1. 레고 월E 굴러가게 하기.

2. 무조건 내 핸드폰 앱으로 컨트롤 가능해야 함. 적외선 컨트롤러 이딴거 난 안쓴다.

3. 블루투스 구성 위한 마인드스톰 오지게 비쌈. 아두이노 사용해서 경비절감.


그리하여 아래와 같이 완성!


외국 친구들한테도 페북 공유하려다보니 못난 영작이 함께 들어갑니다. 리딩 흐름에 방해가 되더라도 양해 부탁드립니다.


During the last final's week, I found the LEGO's brand-new Wall E model. And soon after that, I found another Youtube video Wall-E motorized with LEGO mind storm. It was totally mind blowing work!! So, of course, I've done this project during my winter break. My missions were:

1. LEGO Wall-E Motorized

2. It has to be controlled by my iPhone. I don't wanna talk about the stupid infrared controller at all. :P

3. But, mind storm for bluetooth is freakin' expensive. Use Arduino.

At the end, voila.





Step 1. 부품을 준비한다. Prepare parts we need


Requirement parts:

  1. Lego Wall-E : $60.
  2. Motors : LEGO Power Functions M-Motor. (9v 65mA) $7 x 2 = $14.
  3. Lego Pick-a-brick : For connecting motor. 4pcs = $1
  4. Arduino UNO Rev3 : $25.
  5. Bluetooth module : HM-10. $9.
  6. 9v battery holder with on/off switch : $2
  7. 9v batteries : $3
  8. L293D Motor Drive Shield Board : $5
  9. Wires : Male to female 40pcs = $1


Total cost: $120



Step 2. 아뒤노 하드웨어 부품을 연결한다. Build Arduino hardware parts



나의 모터쉴드는 아두이노 위에 겹쳐서 꼽는 방식이었다. 그 후 모터 연결하고 전원 연결은 모터 쉴드에다 하면 되고, 블루투스 모듈은 와이어를 이용해서 그림과 같이 해당 핀에 분선하여 연결한다. 나의 경우 TX를 3번 핀, RX를 2번 핀에 연결 했다. (모터 컨트롤 핀으로 쓰이지 않는 것을 선택해야 한다. 참고로 0번과 1번, 즉 아두이노 보드의 TX와 RX는 USB와 연결된 프로그램 업로드 용이므로 사용을 피한다.)


My motor shield can be over-layered with the Arduino board. Motors and power (battery) are connected onto the motor shield, bluetooth module needs additional wires to branch from the Arduino. I used pin 3 as TX, and  pin 2 as RX. (You should choose the pins, which are not used for motor controlling. Besides, we should avoid to use pin 0 and 1 because these are for program uploading of Arduino board.)



Step 3. 아두이노에 모터 제어 프로그램을 업로딩한다. 

Upload a motor control program to Arduino.




아두이노를 컴퓨터에 연결하고, Arduino 공식 사이트에서 프로그램 업로드 소프트웨어를 다운받아 설치한다. 

Tools 메뉴에서 Board 를 Arduino Uno 로 선택한다. 코드를 작성 후 업로드 버튼을 눌러 아두이노 보드에 작성한 코드 프로그램을 업로딩한다. 참고로, 고맙게도 모터관련 라이브러리가 이미 제작되어 있다. 이를 이용하면 모터 제어를 쉽게 짤 수 있다. AFMotor임.

https://learn.adafruit.com/adafruit-motor-shield/library-install

위 URL로 들어가면 github 다운로드 링크가 나온다. 다운받은 폴더를 아뒤노 개발툴 라이브러리 폴더 안에 넣고 (e.g. ~/Arduino/libraries/AFMotor) AFMotor.h 파일을 아뒤노 코드에 인클루드 시키면 사용할 수 있다. 

내가 짠 아뒤노 코드는 이 글 최하단에 추가하였으니 참고바람.


참고로 HM-10의 커맨즈는 다음과 같다. 아뒤노 시리얼 모니터에서 입력해보고 정상적으로 응답이 오는지 확인하자. 또한 시리얼 하단에서 no line ending 옵션으로 되어 있는지도 확인한다. 

  • "AT" 전송 시 응답 "OK"
  • "AT+VERR?" 전송 시 응답은 현재 버젼 출력 
  • 이름변경: "AT+NAMEmyWallEBLT" 전송 시 응답 "OK+SET..."
  • 비번변경: "AT+PIN1234" 전송 시 응답 "OK+SET..." (디폴트:000000)
  • 스래이브/마스터변경: "AT+ROLE0" 전송 시 응답 "OK+SET:0" (디폴트: 0 슬래이브. 1은 마스터를 의미.)


Connect the Arduino to a laptop, open a developing software tool downloading from the official Arduino website.

Make sure whether choose 'Arduino Uno' on the Tools menu. Upload a code onto Arduino board. Fortunately, there is a DC motor control library for Arduino already. We can make a motor controlling code easily by using this library, named AFMotor.

https://learn.adafruit.com/adafruit-motor-shield/library-install

You can see github download link when you get into the above URL. Put the library folder into a library folder located under the Arduino developer tool folder, we can use AFMotor after include AFMotor.h file in the code.

My code is at the bottom of this article. 


Note that, HM-10 commands are following: 

  • Send "AT", receive "OK"
  • Send "AT+VERR?", receive a version of bluetooth firmware.
  • Set name: send "AT+NAMEmyWallEBLT", receive "OK+SET..."
  • Set pin: send "AT+PIN1234", receive "OK+SET..." (Default: 000000)
  • Set role: send "AT+ROLE0", receive "OK+SET:0" (Default: 0, means slave. 1 is master mode)
Send these commend to bluetooth through Arduino tool's serial monitor, check whether an answer comes correctly. Make sure the 'no line ending' option is selected at the bottom of the serial monitor.




Step 4. 아이폰 블루투스 컨트롤러 앱을 제작한다. Develop iPhone bluetooth controller app.




그냥 뭐... 잘 짜면 된다...;; 역시 하단에 필요 코드를 첨부하였다. 프로젝트는 기본 Single View 프로젝트로 생성하면 되고, Swift가 아닌 Object C 코드이다. 컴파일 후 아이폰에 올리고 실행하면 위 사진 왼쪽 화면이 나온다. (블루투스가 켜진 상태여야 함.) 내 월E 블루투스를 선택하면, 커넥션 성공 시 오른쪽 화면으로 이동하게 된다. 이것저것 눌러봐서 모터가 잘 도는지 확인한다. 


Well.. good luck. :P. It's hard to explain. I attached essential codes I wrote at the bottom of this article as well.  You need to create a project as a single view project using Xcode. My codes are written by objective C, not Swift. After compile and upload your app onto your iPhone, you can see a screen like the above left picture when you start the app. (It has to be a bluetooth on.) After choose your wall-e bluetooth device, it would move to a screen like the above right picture if it makes the connection successful. Click some buttons to see motor working well.  



Step 5. 월E를 조립한 후 조립 해 둔 하드웨어 부품을 부착한다.

Assemble the Arduino hardware parts onto the Wall-E.



일단 바퀴에 모터 두개 부착. First, attach the two motors with the wheels.



배터리는 배안에 넣어주고 전선은 목 옆쪽 공간을 통해 밖으로 빼준다.

Put a battery into the belly space of Wall-E, wires need to be out through the gap of the neck.



요런식으로 나는 등뒤에 전기테잎으로 고정하였다... 전테말고 다른 방법을 강구하고 싶지만..

(누가 우리 월E 배낭 좀 만들어주시오. ㅎㅎㅎ)


I used an electrical tape to attach the parts at the backside like above. 

I wanna use other things like a backpack or something tho..





Complete!!!








Appendix


* 모터의 선택 : 월E에 실리콘 떡질해서 모터 고정시키고 싶지 않아서 레고 모터 사용. 추가적으로 이때문에 3번 항목 구입 발생.. 모터랑 월E 바퀴 연결부품인데 필요한 브릭만 레고사에서 주문 가능.

* Selection of motors : I used LEGO motors because I don't want to use a sticky messy silicon glue on my Wall-E. That's why my 3rd purchase, pick-a-bricks, was occurred. You can make order from LEGO for picking some little amount of parts what you exactly need for connecting wheels and motors.  


* 라즈베리 파이에 대해 : 이왕이면 더 가지고 놀게 많은 PI 를 사려고 했으나, 이게 컴터 메인보드 같은거라 배터리로 안되고 파워 지속공급 되야 함. 즉, 유선 월E가 된다는 황당한 시츄에이션이... -_- (그거슨 있어서는 안되는 일이야..)

* About the Rasberry PI: We all know the PI is more versatile, however, it is kind of a mainboard, so it needs continuous power supply. It means, my Wall-E will have a stupid wire from a laptop. ABSOLUTELY NOT ALLOWED.


* 블루투스 모듈: HC-05 나 HC-06 많이들 쓰는데, 안드로이드는 이거 써도 됨. 허나 아이폰 6 부터는 블루투스 4.0 이라서 안잡힘. 이거 몰랐어서 블루투스 4.0 쓰는 HM-10으로 다시 샀음. (내 돈...)

* Bluetooth module: HC-05 or HC-06 are mostly common to use for Android application. But iPhone 6 or later have bluetooth 4.0, it cannot scan those modules. I bought HM-10 again after HC-05 because I didn't know that. 


* 모터 드라이버 쉴드: 걍 젤 싼거, 모터 두개 이상 돌릴 수 있는거로 사면 됨. 모터 쉴드는 모터 연결 편리성과 파워를 안전정으로 공급하기 위해 씀. 좀 더 자세히 말하면, 첫째는, 일반적으로 모터는 높은 전류 필요로 함. (레고 모터도 65mA임) 허나 아두이노는 핀당 20mA 출력함. 드라이버가 이를 충분한 전압과 전력으로 출력할 수 있게 해 줌. 둘째는, 모터 회전 방향 변경을 하려면 + - 바꿔줘야 하는데, 이를 위한 복잡한 전선 연결을 해결해 줘서 편리하게 방향 변경할 수 있게 해줌. (그때가 납땜에 영혼을 불사를 수 있다면 직접 해도 될듯함...) 더 자세한 내용은 네이버 아두이노 카페 글 참고 http://cafe.naver.com/arduinostory/30555

* Motor driver shield: Just bought a cheapest one, which can manage more than two motors. Motor shield is for convenience of connecting motors and provides sufficient power. In detail, first, motors require high current value mostly. (LEGO M motor is also 65mA.) But Arduino has only 20mA per pin. Driver makes it can output enough voltage and current for motors. Second, it should change the direction of + and - to change the direction of motor rotating, wire connecting is quite annoying and messy job. Driver handle this issue, it provides a pleasant environment to use multiple motors changing direction.


* 기타 제작 과정에서 도움 받은 참고 자료 및 사이트 Additional useful references. 

LEGO Wall-E 21303 Motorized with Power Functions https://youtu.be/3_9q6RjB5nM

Controlling LEGO DC motor with an Arduino https://youtu.be/PtinpaVpHeo

IPhone to Arduino using Bluetooth 4.0 http://www.instructables.com/id/IPhone-to-Arduino-using-Bluetooth-40-/

Core Bluetooth Programming Guide https://developer.apple.com/library/...

Bluetooth 4.0 datasheet http://www.pridopia.co.uk/pi-doc/BT4.0-HM-10-Serial_Port_BLE_Module_Master_Slave.pdf


* 아두이노 모터 제어 코드 Arduino motor control code.


Note 1:  모든 DC 모터는 조금씩 베이스 속도가 다르다. 이를 동일하게 맞추려면 휴리스틱한 방법으로, 두 모터의 속도 스케일 차이를 파악한 후 속도를 조정해야 한다. 뭔 말이냐면, 1번과 2번 모터를 모두 속도 10으로 맞추었는데, 육안으로 봤을때 2번 모터가 1번보다 3배 빠르게 돌아가고 있다면, 구동전에 1번 모터 속도를 30으로 2번 모터 속도를 10으로 맞추고 구동을 한다는 말이다. 


Note 2: 레고 모터는 AFMotor 라이브러리를 이용한 속도 세팅 시, 90 이하의 속도 세팅에서는 아예 구동하지 않는다.


#include <SoftwareSerial.h>

#include <AFMotor.h>

#define SPD1  100                    // Motor1 base speed.

#define SPD2  165                    // Motor2 base speed.


AF_DCMotor motor1(1);            // Motor1 is connected to slot 1.

AF_DCMotor motor2(4);          // Moter2 is connected to slot 4. 

SoftwareSerial BTSerial(3, 2);  // Pin3 is for TX, and Pin 2 is for RX.

int cmd1 = RELEASE;

int cmd2 = RELEASE;

int unavailableCount = 0;

String cmds = "";


void setup()

{

  Serial.begin(9600);

  BTSerial.begin(9600);

  Serial.println("Jisun's Wall-E world!!");

  motor1.setSpeed(SPD1);

  motor2.setSpeed(SPD2);

}


void loop()

{

  if(BTSerial.available())

  {

    char cmd = BTSerial.read();

    cmds = cmds + cmd;

    unavailableCount = 0;

  }

  else

  {

    unavailableCount = unavailableCount + 1;

  }

  

  if ( unavailableCount > 10 && cmds.length() > 0 )

  {

    int spd1 = SPD1;

    int spd2 = SPD2;

    String dbgstr = "";

    

    if ( cmds.indexOf("speed") >=0 )

    {

      int spdlv = 1;

      if ( cmds == "speed1") spdlv = 1;

      else if ( cmds == "speed2") spdlv = 2;

      else if ( cmds == "speed3") spdlv = 3;

      

      spd1 = spd1 + spdlv * 25;

      spd2 = spd2 + spdlv * 20;

      dbgstr = "Set speed level: " + String(spdlv);

      motor1.setSpeed(spd1);

      motor2.setSpeed(spd2);

    }

    else if ( cmds == "forward" )

    {

      dbgstr = "Move forward";

      cmd1 = FORWARD; cmd2 = FORWARD;

    }

    else if ( cmds == "backward" )

    {

      dbgstr = "Move backward";

      cmd1 = BACKWARD; cmd2 = BACKWARD;

    }

    else if ( cmds == "left")

    {

      dbgstr = "Turn left";

      cmd1 = RELEASE; cmd2 = FORWARD;

    }

    else if ( cmds == "right")

    {

      dbgstr = "Turn right";

      cmd1 = FORWARD; cmd2 = RELEASE;

    }

    else if ( cmds == "leftback")

    {

      dbgstr = "Turn left backward";

      cmd1 = RELEASE; cmd2 = BACKWARD;

    }

    else if ( cmds == "rightback")

    {

      dbgstr = "Turn right backward";

      cmd1 = BACKWARD; cmd2 = RELEASE;

    }

    else if ( cmds == "release" )

    {

      dbgstr = "Release";

      cmd1 = RELEASE; cmd2 = RELEASE;

    }


    if ( dbgstr.length() > 0 )

    {

      dbgstr += "(" + String(spd1) + "/" + String(spd2) + ")";

      Serial.println(dbgstr);

      motor1.run(cmd1);

      motor2.run(cmd2);

    }

    else

    {

      Serial.println(cmds);

    }

    cmds = "";

    unavailableCount = 0;

  }

  

  if(Serial.available())

  {

    char cmd = Serial.read();

    BTSerial.write(cmd);

  }

}



* 아이폰 블루투스 컨트롤러 코드 iPhone bluetooth controller code


ViewController.h


//

//  ViewController.h

//  WallEController

//

//  Created by Jisun Kang on 1/10/16.

//  Copyright © 2016 ___JSK___. All rights reserved.

//


#import <UIKit/UIKit.h>

#import <CoreBluetooth/CoreBluetooth.h>


@interface ViewController : UIViewController <CBCentralManagerDelegate>

@property (nonatomic, strong) CBCentralManager *centralManager;

@property (nonatomic, strong) CBPeripheral *peripheral;

@property (nonatomic, strong) CBCharacteristic *currentcharacteristic;


-(IBAction) goToSecondView:(id)sender;

-(IBAction) cancelConnection:(id)sender;

@end


@interface SecondViewController : UIViewController

@property (nonatomic, strong) CBCentralManager *centralManager;

@property (nonatomic, strong) CBPeripheral *peripheral;

@property (nonatomic, strong) CBCharacteristic *currentcharacteristic;


-(IBAction) pressButtons:(UIButton *)sender;

@end




ViewController.m


//

//  ViewController.m

//  WallEController

//

//  Created by Jisun Kang on 1/10/16.

//  Copyright © 2016 ___JSK___. All rights reserved.

//


#import "ViewController.h"


// this is for various device screen size.

#define SCREEN_WIDTH [[UIScreen mainScreen] bounds].size.width

#define SCREEN_HEIGHT [[UIScreen mainScreen] bounds].size.height


@interface ViewController () <UITableViewDataSource, UITableViewDelegate>

{

    NSMutableArray* cbArray;

}

@property (strong, nonatomic) IBOutlet UITableView *mainTableView;

@property (strong, nonatomic) IBOutlet UILabel *mainLabel;

@end


@implementation ViewController


- (void)viewDidLoad {

    [super viewDidLoad];


    // initializing UITableView

    cbArray = [NSMutableArray array];

    _mainTableView.delegate = self;

    _mainTableView.dataSource = self;

    _mainTableView.backgroundColor = [UIColor colorWithRed:236.0/255.0 green:236/255.0 blue:236.0/255.0 alpha:0.7];

    _mainTableView.backgroundView = nil;

    _mainTableView.allowsMultipleSelectionDuringEditing = NO;

    _mainTableView.separatorStyle = UITableViewCellSeparatorStyleSingleLineEtched;

    _mainTableView.autoresizingMask = UIViewAutoresizingNone;

    

    self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];

    self.peripheral.delegate = self;

}


- (void)viewDidAppear:(BOOL)animated {

    [super viewDidAppear: true];

    _mainLabel.text = @"";

}


- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

}


- (void)dealloc

{

    [self.centralManager stopScan];

}


- (IBAction)goToSecondView:(id)sender {

    UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName: @"Main" bundle:nil];

    SecondViewController* secVC = [mainStoryboard instantiateViewControllerWithIdentifier:@"SecondView"];

    secVC.centralManager = self.centralManager;

    secVC.peripheral = self.peripheral;

    secVC.currentcharacteristic = self.currentcharacteristic;

    [self presentViewController:secVC animated:YES completion:nil];

}


- (IBAction)cancelConnection:(id)sender {

    if ( self.peripheral == nil )

        return;

    _mainLabel.text = @"Cancel connection.";

    [self.centralManager cancelPeripheralConnection:self.peripheral];

    self.peripheral = nil;

    [self.centralManager scanForPeripheralsWithServices:nil options:nil];

}


// =========================================

// CB Central Manager

// =========================================


// Invoked when the central manager’s state is updated.

- (void)centralManagerDidUpdateState:(CBCentralManager *)central

{

    switch (central.state) {

        case CBCentralManagerStatePoweredOn:

            NSLog(@"CoreBluetooth BLE hardware is powered on and ready");

            _mainLabel.text = @"Scanning...";

            [self.centralManager scanForPeripheralsWithServices:nil options:nil]; //@{CBCentralManagerScanOptionAllowDuplicatesKey:@YES}];

            break;

        case CBCentralManagerStatePoweredOff:

        case CBCentralManagerStateResetting:

        case CBCentralManagerStateUnauthorized:

        case CBCentralManagerStateUnknown:

        case CBCentralManagerStateUnsupported:

        default:

            NSLog(@"CoreBluetooth BLE hardware is powered off or not initialized.");

            break;

    }

}


// add the device to our array and reload the table view.

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI

{

    CBPeripheral* currentPer = peripheral;

    

    if(![cbArray containsObject:currentPer])

    {

        [cbArray addObject:currentPer];

    }

    [_mainTableView reloadData];

}


- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral

{

    NSLog(@"Success to connect.: %@",peripheral);

    _mainLabel.text = @"Success to connect.";

    peripheral.delegate = self;

    

    if (peripheral.services) {

        [self peripheral:peripheral didDiscoverServices:nil];

    } else {

        [peripheral discoverServices:nil];

    }

    self.peripheral = peripheral;

}


- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {

    

    NSLog(@"Disconnected with peripheral: %@",peripheral);

    _mainLabel.text = @"Disconnected and scanning...";

    self.peripheral = nil;

    [self.centralManager scanForPeripheralsWithServices:nil options:nil];

    

    NSLog(@"The error is: %@", error.localizedDescription);

}


- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error

{

    NSLog(@"Connection failed to peripheral: %@",peripheral);

    _mainLabel.text = @"Fail to connect.";

}


- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error

{

    for (CBService *service in peripheral.services)

    {

        NSLog(@"Discovered service %@", service);

        _mainLabel.text = @"Discovered service.";

        

        [peripheral discoverCharacteristics:nil forService:service];

    }

}


- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error

{

    NSLog(@"Looking for Characteristic...");

    for (CBCharacteristic *characteristic in service.characteristics)

    {

        if ( characteristic.properties & CBCharacteristicPropertyWriteWithoutResponse )

        {

            NSLog(@"Find Characteristic!!");

            self.currentcharacteristic = characteristic;

            [peripheral setNotifyValue:YES forCharacteristic:characteristic];

        

            [self goToSecondView:nil];

        }

    }

}


- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error

{

    if (error) {

        NSLog(@"Error writing characteristic value: %@",

              [error localizedDescription]);

    }

}


// =========================================

// TableView delegates

// =========================================


#pragma mark UITableView Delegate

// reload the table view when a new peripheral device is found and write their name list.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    static NSString *cellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (cell == nil) {

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];

    }

    

    cell.backgroundColor = [UIColor clearColor];

    cell.selectionStyle = UITableViewCellSelectionStyleDefault;

    

    CBPeripheral* currentPer = [cbArray objectAtIndex:indexPath.row];

    cell.textLabel.text = (currentPer.name ? currentPer.name : @"Not available");

    

    return cell;

}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

    [tableView deselectRowAtIndexPath:indexPath animated:YES];

    

    _mainLabel.text = @"Trying to connect...";

    CBPeripheral* currentPer = [cbArray objectAtIndex:indexPath.row];

    

    if ( self.peripheral != nil )

    {

        [self.centralManager cancelPeripheralConnection:self.peripheral];

    }

    currentPer.delegate = self;

    self.peripheral = currentPer;

    [self.centralManager connectPeripheral:currentPer options:nil];

    

    [self.centralManager stopScan];

}


- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {

    return [NSString stringWithFormat:@"Total count %lu",(unsigned long)cbArray.count];

}


- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section

{

    return 40;

}


#pragma mark UITableView Datasource

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

    return 50;

}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)sectionIndex

{

    return cbArray.count;

}

@end



// =========================================

// SecondViewController

// =========================================


@interface SecondViewController ()

{

}

@property (strong, nonatomic) IBOutlet UILabel *secondLabel;

@end


@implementation SecondViewController


- (void)viewDidLoad {

    [super viewDidLoad];

}


- (void)viewDidAppear:(BOOL)animated {

    [super viewDidAppear: true];

    _secondLabel.text = @"";

}


- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

}


- (IBAction)pressButtons:(UIButton *)sender {

    _secondLabel.text = @"";

    

    NSString *buttonTag = [NSString stringWithFormat:@"%d", (int)sender.tag];

    NSString *data = @"";

    

    switch (sender.tag) {

        case 1:

            _secondLabel.text = @"Turn left";

            data = @"left";

            break;

        case 2:

            _secondLabel.text = @"Go forward";

            data = @"forward";

            break;

        case 3:

            _secondLabel.text = @"Turn right";

            data = @"right";

            break;

        case 4:

            _secondLabel.text = @"Turn left backword";

            data = @"leftback";

            break;

        case 5:

            _secondLabel.text = @"Move backward";

            data = @"backward";

            break;

        case 6:

            _secondLabel.text = @"Turn right backword";

            data = @"rightback";

            break;

        case 0:

            _secondLabel.text = @"Stop";

            data = @"release";

            break;

        case 11:

            _secondLabel.text = @"Slow speed";

            data = @"speed1";

            break;

        case 12:

            _secondLabel.text = @"Normal speed";

            data = @"speed2";

            break;

        case 13:

            _secondLabel.text = @"fast speed";

            data = @"speed3";

            break;

        default:

            break;

    }

    NSLog(_secondLabel.text);

    

    if ( self.currentcharacteristic != nil )

    {

        NSLog(@"Write value to peripheral");

        NSData *encodingdata = [data dataUsingEncoding:NSUTF8StringEncoding];

        

        [self.peripheral writeValue:encodingdata forCharacteristic:self.currentcharacteristic type:CBCharacteristicWriteWithoutResponse];

    }

}

@end