3 Replies Latest reply on Apr 21, 2020 11:19 PM by MoTa_728816

    Application on PSoC 4200L

    SoEL_4655151

      Hi everybody,

      I'm a beginner on PSoC development, and I have an application to do for my project, I have some questions to guide me:

      The application has two operating modes: normal and low consumption.

      After startup, the application directly enters normal mode. It switches to low consumption mode after pressing a button Switch SW1. It returns to normal mode after pressing the SW2 button. (On my card development PSoC 4200L I have two switches: SW1 for reset, and SW2 it's free and I don't know if possible to implement this function, What do you think, if you any suggestion feel free)

      in low consumption mode, nothing happens.

      in normal mode, here is what happens:

       

      > an IDAC produces a fixed current, preconfigured, which passes through a resistance of 15 ohms. The voltage across its terminals is sent to the input of an AOP mounted as a non-inverting gain amplifier x2. The output voltage of this AOP must be equal to 1.65 V (it is, therefore, necessary to adjust the current of the IDAC according to the resistance and the gain).

      > the output voltage of the AOP is converted by an ADC every 2 seconds and transmitted by UART to a PC

      In this case, How can I configure the ADC SAR?

       

      > an LED flashes every second to indicate that the PSoC is in normal mode.

      In this part, I will use just a pin and led or I should use PWM components?

       

      Thanks in advance,

        • 1. Re: Application on PSoC 4200L
          MoTa_728816

          Hi,

           

          There were two points I'd like to mention.

           

          (1) Using SW1 (Reset) for application purpose may be impossible,

          as it is connected to nRESET of the device, so I used SW2

          for both entering and exiting the low-power mode.

           

          (2) For 4200M, max current for a GPIO is 25mA, so if you connect a 16 Ohm it may damage the device.

          And also, the maximum current the internal IDAC can supply is 612uA.

          So I connected 4K (2K + 2K) externally to generate (about) 1.65V (note the current is very small).

           

          So for your application, probably you need an external driver to drive 16 Ohm load.

           

          Anyway, following is a sketch of mine.

           

          I tried with CY8CKIT-044 (4200M) as I don't have a board with 4200L.

          But I hope that if you change the device and pin assignment, probably program will work .

           

          schematic

          001-schematic.JPG

           

          pins

          002-pins.JPG

           

          main.c

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

          #include "project.h"

          #include "stdio.h"

           

          #define STR_LEN 32

          char    str[STR_LEN+1] ;

          void    print(char *str)

          {

              UART_UartPutString(str) ;

          }

           

          void cls(void)

          {

              print("\033c") ; /* reset */

              CyDelay(20) ;

              print("\033[2J") ; /* clear screen */

              CyDelay(20) ;

          }

           

          void splash(char *prog_name)

          {

              cls() ;

              if (prog_name && *prog_name) {

                  print(prog_name) ;

              }

              print(" (") ;

              print(__DATE__) ;

              print(" ") ;

              print(__TIME__) ;

              print(")\n") ;

          }

           

          #define LED_ON  (0u)

          #define LED_OFF (1u)

           

          volatile int sw2_flag = 0 ;

           

          CY_ISR(sw2_isr)

          {

              SW2_ClearInterrupt() ;

              sw2_flag = 1 ;

          }

           

          void init_hardware(void)

          {

              CyGlobalIntEnable; /* Enable global interrupts. */   

              LED_Write(LED_OFF) ;

              isr_sw2_int_ClearPending() ;

              isr_sw2_int_StartEx(sw2_isr) ;

              IDAC_Start() ;

              ADC_Start() ;

              UART_Start() ;

          }

           

          void sleep(void)

          {

              print("Sleeping ... ") ;

              CyDelay(10) ;

              LED_Write(LED_OFF) ;

              UART_Stop() ;   

              IDAC_Stop() ;

              ADC_Stop() ;

           

              // CySysPmSleep();      // you can also try "sleep"

              CySysPmDeepSleep(); // I used  "deep sleep"

             

              // here we have already woken up

              SW2_ClearInterrupt() ;   

              ADC_Start() ;

              IDAC_Start() ;

              UART_Start() ;

              print("Woke up!\n\r") ;

          }

           

          void measure(void)

          {

              uint16_t raw_count ;

              int16_t  mV ;

             

              ADC_StartConvert() ;

              ADC_IsEndConversion(ADC_WAIT_FOR_RESULT) ;

              raw_count = ADC_GetResult16(0) ;

              mV = ADC_CountsTo_mVolts(0, raw_count) ;

              snprintf(str, STR_LEN, "%d.%03d V\n\r",mV/1000, mV%1000) ;

              print(str) ;

          }

           

          int main(void)

          {

              int count_500ms = 0 ;

              init_hardware() ;

             

              splash("PSoC 4 Sleep and IDAC/ADC test") ;

             

              for(;;)

              {

                  if (sw2_flag) {

                      sleep() ;

                      count_500ms = 0 ;

                      sw2_flag = 0 ;

                  }

                  if (count_500ms % 2) {

                      LED_Write(LED_OFF) ;

                  } else {

                      LED_Write(LED_ON) ;

                  }

                  if (count_500ms == 3) {

                      measure() ;

                  }

                  count_500ms = (count_500ms + 1) % 4 ; // 0, 1, 2, 3, 0, 1...

                  CyDelay(500) ;

              }

          }

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

           

          Tera Term log

          000-TeraTerm-log.JPG

           

          One last thing!

          I used "CyDelay(500)" to make a 0.5 sec delay, but timing error will be accumulated in the long run.

          So if you'd like to have precise timing, please use "SysTick" or other hardware timer.

           

          moto

          • 2. Re: Application on PSoC 4200L
            SoEL_4655151

            Hi,

            Sorry I was a little late to answer you,

            First of all, thank you for the application, I really appreciated.

            Since I have a PSoC 4200L development board and I am limited in the number of switches I tried to modify the specifications.

            For this, here is the new application

            The application has two operating modes: Low consumption and normal mode

            So it will be done through the switch SW2

            in low consumption mode, nothing happens.

            in normal mode, here is what happens:

             

            > an IDAC produces a fixed current, preconfigured, which passes through a resistance of 10 ohms. The voltage across its terminals is sent to the input of an AOP follower. The output voltage of this AOP must be equal to 1.65 V (it is, therefore, necessary to adjust the current of the IDAC according to the resistance).

            > the output voltage of the AOP is converted by an ADC every 2 seconds and transmitted by UART to a PC

            In this case, I use the PWM signal

             

            > an LED flashes every second to indicate that the PSoC is in normal mode.

            In this part, I use a PWM two

            The app adds another RTC component that displays the date and time

            is this function dedicated for the RTC component ?

            void splash(char *prog_name)

            {

                cls() ;

                if (prog_name && *prog_name) {

                    print(prog_name) ;

                }

                print(" (") ;

                print(__DATE__) ;

                print(" ") ;

                print(__TIME__) ;

                print(")\n") ;

            }

            Schematic on PSoC creator:

            Thanks in advance

            • 3. Re: Application on PSoC 4200L
              MoTa_728816

              Hi,

               

              __DATE__ and __TIME__ represents the time and date the project was compiled,

              and it won't change during the run time.

              So we need to use "RTC" to track the time.

               

              And for the uart input, I utilized my tty_utils.

              Re: tty_utils a utility sample for CLI type program

               

              Anyway, I imitated your schematic and tried with CY8CKIT-044

              and later ported the project to CY8CKIT-046 (4200L).

              Note: Since I don't have CY8CKIT-046, I have not tested it with real hardware.

               

              schematic

              002-schematic.JPG

              Tera Term log

              001-TeraTerm-log.JPG

               

              pins

              CY8CKIT-044

              003-pins.JPG

              CY8CKIT-046

              013-pins-046.JPG

              main.c

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

              #include "project.h"

              #include "stdio.h"

              #include "tty_utils.h"

              #include "rtc_utils.h"

               

              #define LED_ON  (0u)

              #define LED_OFF (1u)

               

              volatile int sw2_flag = 0 ;

              volatile int adc_flag = 0 ;

               

              CY_ISR(adc_isr)

              {

                  adc_flag = 1 ;

              }

               

              CY_ISR(sw2_isr)

              {

                  WakeUp_ClearInterrupt() ;

                  isr_sw2wakeup_Disable() ;

                  sw2_flag = 1 ;

              }

               

              void init_hardware(void)

              {

                  CyGlobalIntEnable; /* Enable global interrupts. */   

                  tty_init() ;

                  PWM_LED_Start() ;

                  Non_inverting_OpAmp_Start() ;

                  IDAC_Start() ;

                  isr_sw2wakeup_ClearPending() ;

                  isr_sw2wakeup_StartEx(sw2_isr) ;

                  ADC_Done_ClearPending() ;

                  ADC_Done_StartEx(adc_isr) ;

                  ADC_Start() ;

                  PWM_ADC_Start() ;

              }

               

              void prepare_sleep(void)

              {

                  PWM_ADC_Stop() ;

                  ADC_Stop() ;

                  IDAC_Stop() ;

                  Non_inverting_OpAmp_Stop() ;

                  PWM_LED_Stop() ;

                  PWM_LED_WriteCounter(0) ;

                  LED_Write(LED_OFF) ;

                  UART_Stop() ;

                  isr_sw2wakeup_ClearPending() ;

                  isr_sw2wakeup_Enable() ;

              }

               

              void prepare_wakeup(void)

              {

                  isr_sw2wakeup_ClearPending() ;

                  isr_sw2wakeup_Enable() ;

                 

                  UART_Start() ;

                  PWM_LED_WriteCounter(0) ;

                  PWM_LED_Start() ;

                  Non_inverting_OpAmp_Start() ;

                  IDAC_Start() ;

                  ADC_Start() ;

                  PWM_ADC_WriteCounter(0) ;

                  PWM_ADC_Start() ;

              }

               

              void sleep(void)

              {

                  print("Sleeping ... ") ;

                  CyDelay(10) ;

                  prepare_sleep() ;

               

                  do {

                      CySysPmDeepSleep();

                  } while(sw2_flag == 0) ;

                  sw2_flag = 0 ;

                 

                  // here we have already woken up

               

                  prepare_wakeup() ;

                  print("Woke up!\n\r") ;

              }

               

              void measure(void)

              {

                  uint16_t raw_count ;

                  int16_t  mV ;

                 

                  raw_count = ADC_GetResult16(0) ;

                  mV = ADC_CountsTo_mVolts(0, raw_count) ;

                  snprintf(str, STR_BUF_LEN, "%d.%03d V\n\r",mV/1000, mV%1000) ;

                  print_time() ;

                  print(" ") ;

                  print(str) ;

              }

               

              int main(void)

              {

                  init_hardware() ;

                 

                  splash("Sleep, IDAC, test CY8CKIT-046") ;

                 

                  setup_time() ;

               

                  for(;;)

                  {

                      if (sw2_flag) {

                          sw2_flag = 0 ;

                          sleep() ;

                      }

                      if (adc_flag) {

                          measure() ;

                          adc_flag = 0 ;

                      }

                  }

              }

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

               

              rtc_utils.c

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

              #include "project.h"

              #include "stdio.h"

              #include "tty_utils.h"

              #include "rtc_utils.h"

               

              #define WDT_EACH_1_SEC      (1000)

              #define SYSTICK_EACH_10_HZ  (10u)

              #define SYSTICK_RELOAD      (CYDEV_BCLK__SYSCLK__HZ / SYSTICK_EACH_10_HZ)

               

              void SysTickIsrHandler(void)

              {

                  RTC_Update();

              }

               

              void print_time(void)

              {

                  char time_str[16] ;

                  uint32_t time ;

                 

                  time = RTC_GetTime();

               

                  /* Print Date and Time to UART */

                  sprintf(time_str, "%02lu:%02lu:%02lu", RTC_GetHours(time), RTC_GetMinutes(time), RTC_GetSecond(time));

                  print(time_str) ;

              }

               

              void print_date(void)

              {

                  char date_str[16] ;

                  uint32_t date ;

                 

                  date = RTC_GetDate();

               

                  sprintf(date_str, "%02lu/%02lu/%02lu", RTC_GetYear(date), RTC_GetMonth(date), RTC_GetDay(date));    

                  print(date_str) ;

              }

               

              void setup_time(void)

              {

                  uint32_t year, month, day ;

                  uint32_t hour, min, sec ;

                  uint32_t input_time, input_date ;

                 

                  print("Enter date (YYYY/MM/DD) > ") ;

                  while(get_line() == 0) { }

                  sscanf(str, "%ld/%ld/%ld", &year, &month, &day) ;

                  year  = RTC_ConvertDecToBCD(year) ;

                  month = RTC_ConvertDecToBCD(month) ;

                  day   = RTC_ConvertDecToBCD(day) ;

                  input_date = ((uint32_t)(year  << RTC_YEAR_OFFSET)  | \

                                (uint32_t)(month << RTC_MONTH_OFFSET) | \

                                (uint32_t)(day   << RTC_DAY_OFFSET))  ;

                 

                  print("Enter time (hh:mm:ss) > ") ;

                  while(get_line() == 0) { }

                  sscanf(str, "%ld:%ld:%ld", &hour, &min, &sec) ;

                  hour = RTC_ConvertDecToBCD(hour) ;

                  min  = RTC_ConvertDecToBCD(min) ;

                  sec  = RTC_ConvertDecToBCD(sec) ;

                  input_time = ((uint32_t)(hour << RTC_HOURS_OFFSET)    | \

                                (uint32_t)(min  << RTC_MINUTES_OFFSET)  | \

                                (uint32_t)(sec  << RTC_SECONDS_OFFSET)) ;

                 

                  RTC_Start() ;

                 

                  RTC_SetDateAndTime(input_time, input_date) ;

                 

                  print("Time Set to: ") ;

                  print_date() ;

                  print(" ") ;

                  print_time() ;

                  print("\n\r") ;

              }

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

               

              moto