cancel
Showing results for 
Search instead for 
Did you mean: 

PSoC 5, 3 & 1 MCU

New Contributor II

Hi there, i need to convert a weight into voltage.

i got a scale (KERN PCB) i am using UART to read the info and USBUART to see it on my computer.

teraterm.PNG

My measures are from 0 to 2500 gr - so for the conversion to voltage i want to use PWM with a period of 2500 and Compare value that come from the scale (KERN PCB).

  • i got a problem collecting the data and put it in the PWM Compare function.

The data that i get from the scale is an 8 bits ascii characters.

this is my code:

#include "project.h"

#include "stdio.h"

#include <stdlib.h>

#define USBFS_DEVICE    (0u)

int main()

{

    CyGlobalIntEnable

    LCD_Start();

    USBUART_Start(USBFS_DEVICE, USBUART_5V_OPERATION);

    UART_Start();

    PWM_Start();

    char8 ch = 0;

   

 

    for(;;)

    {

            ch = 0;   

            ch = UART_GetChar();

           

            if(ch > 0u)

          {

             USBUART_PutChar(ch);

          }

              

            PWM_WriteCompare(ch);

    }

       

}

  

i tried to debug the and see the value that "ch" is getting (for better understanding how to handle the data) but im getting an error,

  • first, is it possible to debug communication?
  • second, i connecting 2 cables at the same time to the psoc, i think that the error is due to that.

Capture.PNG

it will be helpful if someone have an idea how to debug or how to handle the data and put it in the PWM Compare function.

Thank you all

Best Regard

Michael

0 Likes
Reply
1 Solution
Esteemed Contributor

Dear Michael-san,

Attached is the version for CY8CKIT-050.

Please connect

P12[6] to TxD of your USB-Serial Adapter

P12[7] to RxD of your USB-Serial Adapter

VSSD to GND of your USB-Serial Adapter

Meantime to see the PWM, I assigned P6[0]

so please connect P6[0] to LED1 (to test)

(1) To test with TeraTerm

Please connect USB-Serial Adapter to TeraTerm (via PC)

At first the program title "uart to pwm" is printed along with its built time.

Then if you type

"1200" the red led (LED1) light about half brightness.

"0" the led turns off

"2500" the led turn of at it full brightness

"0" the led turns off

000-TeraTerm-log.JPG

(2) to connect to the scale (KERN PCB?), connect P12[6], P12[7] and VSSD to KERN PCB.

Then, I hope, we can see the LED's brightness changes according to the scale value.

Now trying to answer your questions...

> in which part of the "get_line()" function the information is derived from the  uart?

In the source "tty_utils.c" the data acquisition from UART is done in an ISR (interrupt service routine)

It only pool the received data into rx_buff[] with rx_write_idex increment.

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

CY_ISR(tty_rx_isr)

{

    if (UART_GetRxBufferSize()) {

        rx_buf[rx_write_index] = UART_GetByte() ;

        rx_write_index = (rx_write_index + 1) % RX_BUF_LEN ;

    }

    tty_rx_int_ClearPending() ;

}

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

Note: Following line make the buffer as a ring buffer.

So when rx_write_index reaches to the last part of the buffer,

it continues from 0.

rx_write_index = (rx_write_index + 1) % RX_BUF_LEN ;

> is this "get_line()" function return a Boolean value? (im trying to understand the "if" below).

int get_line(void) in tty_utils.c returns

(1) length of the line received if it is within the length of STR_BUF_LEN

(2) -1 if the line was exceeding STR_BUF_LEN, to stop overflow get_line() terminate the string after the last letter within STR_BUF_LEN

     to do this, str[] was defined as char str[STR_BUF_LEN+1].

(3) 0 if the receiving line is still go on.

So following block was

(1) get_line() returns 0 when input is not terminated with EOL, so the followning block is skipped

(2) get_line() returns -1 or the length of received line when a new line  Line Feed ('\n') or Carriage Return ('\r') was received after some letters.

    Then program enters the block following the if ().

>    compare = str2pwm(str) ;

This line convert str, which is the received line to an integer value.

From your TeraTerm log, I assumed that the scale sends something like "1936.79 g".

At first I search '.' and if there is '.' in the str, I replace the letter with (char)0,

this way, the str is now "1936".

Then sscanf(str, "%hd",  &value) converts the strings "1936" to an integer 1936.

So compare is assigned the first integer value of the line received.

From the line /* set compare */

(1) Stop PWM before modifying parameter. : PWM_Stop() ;

(2) Reset the count value to 0 or if the count value is larger than compare

     it may run long time till the end of the counter : PWM_WriteCounter(0) ;

(3) Set the new compare value : PWM_WriteCompare(compare) ;

(4) Restart PWM by calling PWM_Enable() ;

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

    if (get_line()) { // got a line

            compare = str2pwm(str) ;

            /* set compare */

            PWM_Stop() ;

            PWM_WriteCounter(0) ;

            PWM_WriteCompare(compare) ;

            PWM_Enable() ;

    }

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

Best Regards,

23-Oct-2019

Motoo Tanaka

View solution in original post

0 Likes
Reply
4 Replies
Esteemed Contributor

Hi,

This is my quick hack, taking care of only input part of the uart input.

I used CY8CKIT-059 and UART is only via KitProg.

I cheated using my uart tty sample.

tty_utils a utility sample for CLI type program

get_line() read up to EOL and return char str[] ;

Then I check if it has '.' inside and make that char to NULL so that only integer part will be a valid string.

So uart input something like both

1359.62 g

and

2349

will work (I hope)

main.c

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

#include "project.h"

#include "stdio.h"

#include "string.h"

#include "tty_utils.h"

void init_hardware(void)

{

    tty_init() ;

    PWM_Start() ;

    CyGlobalIntEnable; /* Enable global interrupts. */

}

uint16_t str2pwm(char *str)

{

    char *ptr ;

    uint16_t value = 0 ;

    ptr = strchr(str, '.') ; /* find '.' */

    if (ptr) {

        *ptr = (char) 0 ; /* terminate the string at '.' */

    }

    sscanf(str, "%hd", &value) ;

    return(value) ;

}

int main(void)

{

    uint16_t compare ;

   

    init_hardware() ;

    splash("uart to pwm") ;

// prompt() ; /* for human input */

    for(;;) {

        if (get_line()) { // got a line

            compare = str2pwm(str) ;

            /* set compare */

            PWM_Stop() ;

            PWM_WriteCounter(0) ;

            PWM_WriteCompare(compare) ;

            PWM_Enable() ;

        }

    }

}

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

moto

New Contributor II

Hi moto, thank you very much for the reply!

im using CY8CKIT-050     'CY8C5868AXI-LP035'

  • there is a way that i can modify the project that you attached for my kit?

also i tried to use some of your code on my project, but unfortunately my coding skills are not good as yours (yet )

therefore i got confused.

can you please explain me :

  • in which part of the "get_line()" function the information is derived from the  uart?
  • is this "get_line()" function return a Boolean value? (im trying to understand the "if" below).

if (get_line()) { // got a line

            compare = str2pwm(str) ;

            /* set compare */

            PWM_Stop() ;

            PWM_WriteCounter(0) ;

            PWM_WriteCompare(compare) ;

            PWM_Enable() ;

        }

  • how the information is getting into str ?

int get_line(void)

{

    int result = 0 ;

   

    if (rx_read_index != rx_write_index) {

        if (is_eol(rx_buf[rx_read_index])) {

            str[str_buf_index] = (char)NULL ;

            result = str_buf_index ;

            str_buf_index = 0 ;

        } else {

            str[str_buf_index++] = rx_buf[rx_read_index] ;

            if (str_buf_index >= STR_BUF_LEN) {

                str[STR_BUF_LEN] = (char)NULL ;

                str_buf_index = 0 ;

                result = -1 ; /* str buf overflow */

            }

        }

        rx_read_index = (rx_read_index + 1) % RX_BUF_LEN ;

    }

    return( result ) ;

}

  • i am sure that most of my confusion is due to the fact that im not familiar with low end coding, do you familiar with a tutorial about it? is it special coding for arm processors?

I hope that its is not a lot of trouble for you,

thank you very much !

Michael

0 Likes
Reply
Esteemed Contributor

Dear Michael-san,

Attached is the version for CY8CKIT-050.

Please connect

P12[6] to TxD of your USB-Serial Adapter

P12[7] to RxD of your USB-Serial Adapter

VSSD to GND of your USB-Serial Adapter

Meantime to see the PWM, I assigned P6[0]

so please connect P6[0] to LED1 (to test)

(1) To test with TeraTerm

Please connect USB-Serial Adapter to TeraTerm (via PC)

At first the program title "uart to pwm" is printed along with its built time.

Then if you type

"1200" the red led (LED1) light about half brightness.

"0" the led turns off

"2500" the led turn of at it full brightness

"0" the led turns off

000-TeraTerm-log.JPG

(2) to connect to the scale (KERN PCB?), connect P12[6], P12[7] and VSSD to KERN PCB.

Then, I hope, we can see the LED's brightness changes according to the scale value.

Now trying to answer your questions...

> in which part of the "get_line()" function the information is derived from the  uart?

In the source "tty_utils.c" the data acquisition from UART is done in an ISR (interrupt service routine)

It only pool the received data into rx_buff[] with rx_write_idex increment.

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

CY_ISR(tty_rx_isr)

{

    if (UART_GetRxBufferSize()) {

        rx_buf[rx_write_index] = UART_GetByte() ;

        rx_write_index = (rx_write_index + 1) % RX_BUF_LEN ;

    }

    tty_rx_int_ClearPending() ;

}

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

Note: Following line make the buffer as a ring buffer.

So when rx_write_index reaches to the last part of the buffer,

it continues from 0.

rx_write_index = (rx_write_index + 1) % RX_BUF_LEN ;

> is this "get_line()" function return a Boolean value? (im trying to understand the "if" below).

int get_line(void) in tty_utils.c returns

(1) length of the line received if it is within the length of STR_BUF_LEN

(2) -1 if the line was exceeding STR_BUF_LEN, to stop overflow get_line() terminate the string after the last letter within STR_BUF_LEN

     to do this, str[] was defined as char str[STR_BUF_LEN+1].

(3) 0 if the receiving line is still go on.

So following block was

(1) get_line() returns 0 when input is not terminated with EOL, so the followning block is skipped

(2) get_line() returns -1 or the length of received line when a new line  Line Feed ('\n') or Carriage Return ('\r') was received after some letters.

    Then program enters the block following the if ().

>    compare = str2pwm(str) ;

This line convert str, which is the received line to an integer value.

From your TeraTerm log, I assumed that the scale sends something like "1936.79 g".

At first I search '.' and if there is '.' in the str, I replace the letter with (char)0,

this way, the str is now "1936".

Then sscanf(str, "%hd",  &value) converts the strings "1936" to an integer 1936.

So compare is assigned the first integer value of the line received.

From the line /* set compare */

(1) Stop PWM before modifying parameter. : PWM_Stop() ;

(2) Reset the count value to 0 or if the count value is larger than compare

     it may run long time till the end of the counter : PWM_WriteCounter(0) ;

(3) Set the new compare value : PWM_WriteCompare(compare) ;

(4) Restart PWM by calling PWM_Enable() ;

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

    if (get_line()) { // got a line

            compare = str2pwm(str) ;

            /* set compare */

            PWM_Stop() ;

            PWM_WriteCounter(0) ;

            PWM_WriteCompare(compare) ;

            PWM_Enable() ;

    }

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

Best Regards,

23-Oct-2019

Motoo Tanaka

View solution in original post

0 Likes
Reply
New Contributor II

wow, thank you very much Motoo !

its work !

also I learned a lot from your code, i really appreciate it!

Best Regards

Michael