0

I need to send 6 bytes value from Arduino UNO to the actuator using serial port in order to make it extends. I have added a button to send the data. For example, 0 20 1 1 0 0. The communication settings are 9600 baud rate, 8 data bits, no parity and 1 stop bit. I have used MAX 232 to build a TTL to RS232 circuit. The actuator does not move. Are there any problems on my program? I am new to create USART code. I think I have some problems on transmit function. I am using the build in USART with c code. Here is my code:

#define BAUD_PRESCALER 0x67
int buttonPin1 = 4;
int buttonState1 = 0;

void setup() {
    // put your setup code here, to run once:
    pinMode(buttonPin1, INPUT_PULLUP);
}

unsigned char data1 = 0x00; // 0
unsigned char data2 = 0x14; // 20
unsigned char data3 = 0x01; // 1
unsigned char data4 = 0x01; // 1
unsigned char data5 = 0x00; // 0
unsigned char data6 = 0x00; // 0

void USART_Init(void) {
    /*Set baud rate */
    UBRR0 = BAUD_PRESCALER;
    UCSR0A = 0x00;
    /*Enable receiver and transmitter */
    UCSR0B = 0x08;
    /* Set frame format: 8data, 1stop bit */
    UCSR0C = 0x06;
}

void USART_Transmit( unsigned char data ) {
    /* Wait for empty transmit buffer */
    while ( !( UCSR0A & (1<<UDRE0)) )
    {
        ;
    }
    /* Put data into buffer, sends the data */
    UDR0 = data;
}

void loop() {
    // put your main code here, to run repeatedly:
    buttonState1 = digitalRead(buttonPin1);
    if (buttonState1 == LOW)
    {
        USART_Init();
        USART_Transmit(data1);
        USART_Transmit(data2);
        USART_Transmit(data3);
        USART_Transmit(data4);
        USART_Transmit(data5);
        USART_Transmit(data6);
    }
}
  • 1
    Link to the actuator data sheet, please. – Scott Seidman Apr 3 '17 at 10:47
  • 2
  • sorry my bad... – kamchai Apr 3 '17 at 10:52
  • 2
    It is not the main problem just a note,USART_init does not have to be called every time, it is enough if you call it in setup(). – Bence Kaulics Apr 3 '17 at 12:09
  • The comment /*Enable receiver and transmitter */ is incorrect: you are only enabling the transmitter. – Edgar Bonet Apr 3 '17 at 21:12
2

The first thing I do when I have a transceiver that doesn't work is a loopback test. This rules out a lot of potential issues like the wrong pin being used or MAX 232 not being connected correctly.

Receiving your transmission on a PC using USB to RS232 adapter (if you have one) would also be a helpful test.

1

I would recommend you to use the arduino's built in UART library. Try this code:

int buttonPin1 = 4;
int buttonState1 = 0;

unsigned char data1 = 0; 
unsigned char data2 = 20;
unsigned char data3 = 1;
unsigned char data4 = 1;
unsigned char data5 = 0;
unsigned char data6 = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);           // set up Serial library at 9600 bps
  while (!Serial);              // wait till UART initialized, for arduino UNO

  pinMode(buttonPin1, INPUT_PULLUP);
}


void loop() {
    // put your main code here, to run repeatedly:
    buttonState1 = digitalRead(buttonPin1);
    if (buttonState1 == LOW)
    {
        Serial.write(data1);
        Serial.write(data2);
        Serial.write(data3);
        Serial.write(data4);
        Serial.write(data5);
        Serial.write(data6);
    }
}

You should know that as long as the button is pressed data is being sent to the actuator. With that being said, with one button press you may have the commands sent 10 times. Thus, you have to deal with that in your code.

  • Thank you for your comment. I have tried to use your code but there was only a blink of yellow LED that indicates the existence of serial communication. The actuator did not move. One thing I am not clear, why I need to deal with the commands that may sent 10 times? – kamchai Apr 3 '17 at 17:23
  • Since the code is executed in a loop void loop() and the if statement if (buttonState1 == LOW) is true, UART data is going to be sent as long as the button is pressed even though it is pressed for just 30ms or 40ms. The program scanning is much more faster than a couple of milliseconds. – Macit Apr 3 '17 at 17:43
  • The actuator should go to the absolute position 275 microsteps and stop there. Can you change the linear position of the actuator by hand and try again – Macit Apr 3 '17 at 17:53
  • I have changed the position of the actuator manually to original position and send the move absolute command once, but it does not move. I am wondering if the data sent is not in the right form. – kamchai Apr 4 '17 at 7:27
  • To narrow down the problem did you try the Zaber Console it is free and open source. You can find a C lib as well in the same link. – Macit Apr 4 '17 at 9:10
1

I think that your BAUD rate setting is wrong. The UBRR0 register is a 16 bit wide one thus should be accessed in two 8 bit part, via UBRR0H and UBRR0L. You can check it in the datasheet.

If you further check the datasheet there is an example code in addition to the USART description which shows a correct way of initialization.

#define FOSC 1843200 // Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1
void main( void )
{
    ...

    USART_Init(MYUBRR)
    ...
}

void USART_Init( unsigned int ubrr)
{
    /*Set baud rate */
    UBRR0H = (unsigned char)(ubrr>>8);
    UBRR0L = (unsigned char)ubrr;
    /* Enable receiver and transmitter */
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);
    ...
}

As you can see the UBRR's value is calculated using the system clock speed FOSC, with MYUBRR macro which is an equation from the datasheet. Later this value is being set in two part upper 8 bit:

UBRR0H = (unsigned char)(ubrr>>8);

lower 8 bit:

UBRR0L = (unsigned char)ubrr;

(Your transmit function seems to be correct. And as I commented it is enough to call the USART init once in the setup().)

  • Splitting the write to UBRR0 may have been needed many years ago, but it is completely useless today: gcc knows very well how to write to a 16-bit I/O register. – Edgar Bonet Apr 3 '17 at 21:04
  • Also, your formula (ok, Atmel's formula) for calculating MYUBRR is bad: it will systematically round down. You should instead use <util/setbaud.h> from avr-libc, which correctly rounds to the nearest integer. Or better yet, use Serial.begin(). – Edgar Bonet Apr 3 '17 at 21:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.