Code Examples Forum Discussions
Hi all,
I made a program to control electronic dice from BLE. The remote control side of BLE used the program of Central that I posted previously as it was, and controlled the start and stop of the dice by the movement of the slider. In the photo, the top is the electronic dice and the bottom is the remote control. The remote control below is connected to the mobile battery to supply power.
The environment used is as follows:
・PSoC Creator 4.2
・CY8CKIT-062-BLE
As for the circuit of the dice, I did not like the circuit I posted last time, so I returned it to the previous one and added the BLE component. Please refer to the previous post for LED placement. The circuit and the pin assignment in PSoC6 are as follows.
The program of BLE event handler is as follows:
void genericEventHandler(uint32_t event, void *eventParameter)
{
cy_stc_ble_gatts_write_cmd_req_param_t *writeReqParameter;
/* Take an action based on the current event */
switch (event)
{
/* This event is received when the BLE stack is Started */
case CY_BLE_EVT_STACK_ON:
case CY_BLE_EVT_GAP_DEVICE_DISCONNECTED:
PWM_BLINK_Start();
Cy_BLE_GAPP_StartAdvertisement(CY_BLE_ADVERTISING_FAST, CY_BLE_PERIPHERAL_CONFIGURATION_0_INDEX);
break;
case CY_BLE_EVT_GATT_CONNECT_IND:
Cy_TCPWM_TriggerReloadOrIndex(PWM_BLINK_HW,PWM_BLINK_CNT_NUM);
Cy_TCPWM_PWM_Disable(PWM_BLINK_HW,PWM_BLINK_CNT_NUM);
break;
case CY_BLE_EVT_GATTS_WRITE_REQ:
writeReqParameter = (cy_stc_ble_gatts_write_cmd_req_param_t *)eventParameter;
if((CY_BLE_LED_GREEN_CHAR_HANDLE == writeReqParameter->handleValPair.attrHandle) ||
(CY_BLE_LED_BLUE_CHAR_HANDLE == writeReqParameter->handleValPair.attrHandle))
{
val = writeReqParameter->handleValPair.value.val[0];
if(val>100) val = 100;
if(val>valp){
PWM_1_SetCounter(0);
PWM_1_SetPeriod0(399);
PWM_1_Start(); // Start rolling dice
sw=1; // sw is on
valp = val;
}
if(val<valp){
/* Roll dice slowly */
PWM_1_SetCounter(0);
PWM_1_SetPeriod0(1999);
CyDelay(1500); // keep rolling slowly for 1.5sec
PWM_1_Disable();// Stop rolling dice
sw=0; // sw is off
valp=0;
}
}
Cy_BLE_GATTS_WriteRsp(writeReqParameter->connHandle);
break;
default:
break;
}
}
Reference information
- Concept of electronic dice: Let's make the dice of seven eyes with PSoC 6 (M4), the protagonist of the game
- PSoC 6 BLE controller (This Code Example is PSoC6_LED_BleCentral.cyfsn.zip):BLE demo using 2 kits
- PSoC 6 Electronic Dice (previous post): Let's make the dice of seven eyes on PSoC 6 with CapSense & sound,the protagonist of the game
Thanks,
Kenshow
Show LessHi,
As I accumulated homework in my previous sample/study,
I wanted attack one by one.
A study of simple oscilloscope using ADC and DMA (CY8CKIT-044) version 1
So the first one I challenged was
Display ADC value into UART without using CPU (except initialization).
As you know, the result of ADC component is a binary value,
I must figure out (aka hack) a way to convert a binary value into UART readable ascii letters.
Of course if we use CPU, it's a peace of cake, but without CPU it was not.
After a few days of struggle I came up with the following trick.
(1) I limit the result value of ADC as 8bit. So it's a couple of ascii letters, such as "00" "1A", etc.
(2) I prepared a couple tables which has the upper letter and the lower letter of the value.
(3) At first I assign the beginning of the above tables into the letter to UART DMA. (DMA_ASC_H and DMA_ASC_L)
(4) Each ADC results, the value will be DMAed to the LSB of each table address variable(s). (DMA_RAW_H and DMA_RAW_L)
Note: As a register is 4 bytes structure, I needed to create a 4 bytes variable then DMA the variable word to word.
(5) Then the table address value will be DMAed to the source address of Letter to UART DMA. (DMA_H_ADR and DMA_L_ADR)
The higher nibble letter table
Note: For the trick, the table is aligned to 0x100 boundary.
======================
const uint8_t ascii_h[256]
__ALIGNED(0x100u)
= {
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
'1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
'3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
'4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
'5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
'6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
'7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
'8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
'9', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B',
'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C',
'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E',
'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F'
} ;
======================
The lower nibble letter table
Note: For the trick, the table is aligned to 0x100 boundary.
======================
const uint8_t ascii_l[256]
__ALIGNED(0x100u)
= {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
} ;
======================
Note ascii_h[0xAB] = 'A' and ascii_l[0xAB] = 'B'
Schematic
Almost a Rube Goldberg machine...
Pins
main.c
========================
#include "project.h"
#include "stdio.h"
#include "tty_utils.h"
#include "ascii_byte_table.h"
#define DEBUG_INFO 0
uint32_t h_char_address = (uint32_t) ascii_h ;
uint32_t l_char_address = (uint32_t) ascii_l ;
uint8_t *h_char = (uint8_t *)&h_char_address ;
uint8_t *l_char = (uint8_t *)&l_char_address ;
volatile int dma_done_flag = 0 ;
CY_ISR(dma_done_isr)
{
dma_done_flag = 1 ;
}
void init_hardware(void)
{
CyGlobalIntEnable; /* Enable global interrupts. */
tty_init() ;
ADC_Start() ;
DMA_PRE_Start( (void *)prefix, (void *)UART_TX_FIFO_WR_PTR) ;
DMA_ASC_H_Start((void *)h_char, (void *)UART_TX_FIFO_WR_PTR) ;
DMA_ASC_L_Start((void *)l_char, (void *)UART_TX_FIFO_WR_PTR) ;
DMA_EOL_Start( (void *)eol, (void *)UART_TX_FIFO_WR_PTR) ;
DMA_H_ADR_Start((void *)h_char, (void *)(&CYDMA_DESCR_BASE.descriptor[DMA_ASC_H_CHANNEL][0].src)) ;
DMA_L_ADR_Start((void *)l_char, (void *)(&CYDMA_DESCR_BASE.descriptor[DMA_ASC_L_CHANNEL][0].src)) ;
DMA_RAW_H_Start((void *)ADC_SAR_CHAN0_RESULT_PTR, (void *)h_char) ;
DMA_RAW_L_Start((void *)ADC_SAR_CHAN0_RESULT_PTR, (void *)l_char) ;
dma_done_int_ClearPending() ;
dma_done_int_StartEx(dma_done_isr) ;
}
void dump_dma_ch(int ch)
{
snprintf(str, STR_BUF_LEN, "DMA%d\n\r", ch) ;
print(str) ;
print("descriptor 0 :") ;
snprintf(str, STR_BUF_LEN, "0x%08X -> 0x%08X CTRL:0x%08X Status:0x%08X\n\r",
(uint32_t)CYDMA_DESCR_BASE.descriptor[ch][0].src,
(uint32_t)CYDMA_DESCR_BASE.descriptor[ch][0].dst,
(uint32_t)CYDMA_DESCR_BASE.descriptor[ch][0].ctl,
(uint32_t)CYDMA_DESCR_BASE.descriptor[ch][0].status
) ;
print(str) ;
print("descriptor 1 :") ;
snprintf(str, STR_BUF_LEN, "0x%08X -> 0x%08X CTRL:0x%08X Status:0x%08X\n\r",
(uint32_t)CYDMA_DESCR_BASE.descriptor[ch][1].src,
(uint32_t)CYDMA_DESCR_BASE.descriptor[ch][1].dst,
(uint32_t)CYDMA_DESCR_BASE.descriptor[ch][1].ctl,
(uint32_t)CYDMA_DESCR_BASE.descriptor[ch][1].status
) ;
print(str) ;
}
void dump_dma(void)
{
print("DMA_RAW_H: ") ;
dump_dma_ch(DMA_RAW_H_CHANNEL) ;
print("DMA_RAW_L: ") ;
dump_dma_ch(DMA_RAW_L_CHANNEL) ;
print("DMA_H_ADR: ") ;
dump_dma_ch(DMA_H_ADR_CHANNEL) ;
print("DMA_L_ADR: ") ;
dump_dma_ch(DMA_L_ADR_CHANNEL) ;
print("DMA_ASC_H: ") ;
dump_dma_ch(DMA_ASC_H_CHANNEL) ;
print("DMA_ASC_L: ") ;
dump_dma_ch(DMA_ASC_L_CHANNEL) ;
print("DMA_PRE: ") ;
dump_dma_ch(DMA_PRE_CHANNEL) ;
print("DMA_EOL: ") ;
dump_dma_ch(DMA_EOL_CHANNEL) ;
print("DMA_ASC_LF: ") ;
snprintf(str, STR_BUF_LEN, "h_char: 0x%08X l_char: 0x%08X\n\r",
h_char_address, l_char_address) ;
print(str) ;
print("\n\r") ;
}
int main(void)
{
init_hardware() ;
splash("ADC-DMAx2 Test") ;
print("\n\r") ;
Timer_Start() ;
for(;;)
{
}
}
========================
Tera Term log
moto
P.S. Diagram for data flow added 25-Oct-2020
Show LessHi all,
In order to study how to turn on and control many LEDs, I created a board with a matrix. I decided to make a roulette wheel using 36 LEDs. This time I will run it with DMA in PSoC4.
The environment used is as follows:
・PSoC Creator 4.4
・CY8CKIT-044
36 LEDs are mounted on the Arduino board, and 12 GPIOs are used to configure a 6x6 matrix. The circuit looks like this:
The actual Arduino board was made as shown in the picture below. There were quite a lot of wiring and it got messed up.
For the circuit, delete the part that was built in the digital hardware last time, and change the data setting of GPIO output to be done by DMA. The circuit and pin layout are as follows.
All three DMA settings are the same. For word transfer, increment the source address (specify array data) and fix the destination address (specify GPIO register address). The Configuration of one of them is shown.
Press the SW2 switch to rotate the roulette wheel, and release it to slow down and stop.
The program is as follows:
#include "project.h"
int data1[6]={0x1F,0x2F,0x37,0x3B,0x3D,0x3E};
int data2[36]={0x08,0x08,0x08,0x08,0x08,0x08,
0x04,0x04,0x04,0x04,0x04,0x04,
0x02,0x02,0x02,0x02,0x02,0x02,
0x01,0x01,0x01,0x01,0x01,0x01,
0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00};
int data3[36]={0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,
0x02,0x02,0x02,0x02,0x02,0x02,
0x01,0x01,0x01,0x01,0x01,0x01};
uint32_t sw=0; //sw is off (Stop rolling dicce)
int main(void)
{
CyGlobalIntEnable; /* Enable global interrupts. */
/* Place your initialization/startup code here (e.g. MyInst_Start()) */
*(int *)0x40040200 = 0x1F; // Initial LED setting
*(int *)0x40040100 = 0x08; // Initial LED setting
*(int *)0x40040300 = 0x00; // Initial LED setting
DMA_1_Start(data1,(void *)0x40040200);
DMA_2_Start(data2,(void *)0x40040100);
DMA_3_Start(data3,(void *)0x40040300);
for(;;)
{
if(sw==0){
// if(Cy_GPIO_Read(SW2_PORT,SW2_NUM)==0){
if(SW2_Read()==0){
PWM_1_WritePeriod(399);
PWM_1_WriteCounter(0);
PWM_1_Start(); // Start rolling dice
sw=1;
}
}
if(sw==1){
//if(Cy_GPIO_Read(SW2_PORT,SW2_NUM)==1){
if(SW2_Read()==1){
/* Roll dice slowly */
PWM_1_WritePeriodBuf(1999);
PWM_1_TriggerCommand(1, PWM_1_CMD_CAPTURE);
CyDelay(1000); // keep rolling slowly for 1sec
PWM_1_WritePeriodBuf(3999);
PWM_1_TriggerCommand(1, PWM_1_CMD_CAPTURE);
CyDelay(1000); // keep rolling slowly for 1sec
PWM_1_WritePeriodBuf(7999);
PWM_1_TriggerCommand(1, PWM_1_CMD_CAPTURE);
CyDelay(1500); // keep rolling slowly for 1sec
PWM_1_Stop(); // Stop rolling
sw=0; // sw is off
}
}
}
}
When you press the SW2 switch, the roulette wheel rotates, and when you release it, it gradually stops slowly.
Thanks,
Kenshow
Show LessHi all,
In order to study how to turn on and control many LEDs, I created a board with a matrix. I decided to make a roulette wheel using 36 LEDs.
The environment used is as follows:
・PSoC Creator 4.3
・CY8CKIT-044
36 LEDs are mounted on the Arduino board, and 12 GPIOs are used to configure a 6x6 matrix. The circuit looks like this:
The actual Arduino board was made as shown in the picture below. There were quite a lot of wiring and it got messed up.
The circuit creates a counter to count 6 by combining the components of Coutner and Compare in column side. It is used to select the De-Multiplexer to select the output.
The row side of the LED matrix is counted after 6 counts. As a result, the lighting of a LED moves to shift like a roulette. The circuit and pin layout are as follows.
Press the SW2 switch to rotate the roulette wheel, and release it to slow down and stop.
The program is as follows:
#include "project.h"
uint32_t sw=0; //sw is off (Stop rolling dicce)
int main(void)
{
CyGlobalIntEnable; /* Enable global interrupts. */
/* Place your initialization/startup code here (e.g. MyInst_Start()) */
// PWM_1_Start();
for(;;)
{
if(sw==0){
// if(Cy_GPIO_Read(SW2_PORT,SW2_NUM)==0){
if(SW2_Read()==0){
PWM_1_WritePeriod(399);
PWM_1_WriteCounter(0);
PWM_1_Start(); // Start rolling dice
sw=1;
}
}
if(sw==1){
//if(Cy_GPIO_Read(SW2_PORT,SW2_NUM)==1){
if(SW2_Read()==1){
/* Roll dice slowly */
PWM_1_WritePeriod(800);
PWM_1_WriteCounter(0);
CyDelay(1000); // keep rolling slowly for 1.5sec
PWM_1_WritePeriod(2000);
PWM_1_WriteCounter(0);
CyDelay(1000); // keep rolling slowly for 1.5sec
PWM_1_WritePeriod(4000);
PWM_1_WriteCounter(0);
CyDelay(1000); // keep rolling slowly for 1.5sec
PWM_1_WritePeriod(8000);
PWM_1_WriteCounter(0);
CyDelay(1500); // keep rolling slowly for 1.5sec
PWM_1_Stop();// Stop rolling
sw=0; // sw is off
}
}
}
}
When you press the SW2 switch, the roulette wheel rotates, and when you release it, it gradually stops slowly.
Thanks,
Kenshow
Show Less
Hi,
Before I posted a similar sample
A Simple Oscilloscope (CY8CKIT-044) using SerialPlotter
But in a discussion below, very fast sampling was required.
May I just measure the PWM pulse with SAR_ADC(CY8CKIT-044)
As I was not familiar with DMA, I have been studying it for a while now.
This sample is the first (somewhat) working version of my simple oscilloscope using ADC and DMA.
It is supposed to be sampling 2us each.
It seems to be working OK, but I want to implement the following 2 functionalities.
Probably in the later versions.
(1) Utilize 2 descriptors to prevent time lag. (But I can not detect it, even with current version using only 1 descriptor, which wonders me.)
(2) Implement a trigger to stop the signal at certain phase. (But I'd like to challenge this after (1))
SerialPoltter Screen
schematic
pins
main.c
Note: as usual I cheated by using my tty_utils.[ch] to make uart hanling easier,
but it's not the main topic of this sample anyway.
====================
#include "project.h"
#include "stdio.h"
#include "tty_utils.h"
#define RESULT_BUF_SIZE 1024
#define SAMPLING_CYCLE 2 /* us */
#define CLOCK_FREQ_MHZ 12
uint16_t result_buf[RESULT_BUF_SIZE] ;
int num_result = RESULT_BUF_SIZE ;
volatile int measured_flag = 0 ;
CY_ISR(meaure_done_isr)
{
measured_flag = 1 ;
}
void init_hardware(void)
{
uint32_t dma_dsc ;
CyGlobalIntEnable; /* Enable global interrupts. */
tty_init() ;
isr_1_ClearPending() ;
isr_1_StartEx(meaure_done_isr) ;
Counter_WritePeriod(num_result) ;
Counter_WriteCounter(0) ;
Counter_Start() ;
ADC_Start() ;
DMA_Start((void *)ADC_SAR_CHAN0_RESULT_PTR, result_buf) ;
dma_dsc = DMA_GetNextDescriptor() ;
DMA_SetNumDataElements(dma_dsc, num_result) ;
Timer_Init() ;
Timer_WritePeriod(SAMPLING_CYCLE * CLOCK_FREQ_MHZ) ;
Timer_WriteCounter(0) ;
}
void clear_buf(void)
{
int i = 0 ;
for (i = 0 ; i < RESULT_BUF_SIZE ; i++ ) {
result_buf = 0 ;
}
}
void dump_buf(void)
{
int i = 0 ;
for (i = 0 ; i < num_result ; i++ ) {
snprintf(str, STR_BUF_LEN, "%d\n\r", result_buf) ;
print(str) ;
}
}
int main(void)
{
int count = 0 ;
init_hardware() ;
splash("ADC-DMA Test") ;
Timer_Start() ;
for(;;)
{
if (measured_flag) {
measured_flag = 0 ;
dump_buf() ;
Counter_WriteCounter(0) ;
Timer_WriteCounter(0) ;
Timer_Start() ;
}
}
}
====================
moto
Show LessDear Arath-san and for those who may be interested,
I created a sample project using CY8CKIT-044.
Request
==========================
What will be the code for:
When the ADC measure 4V display the label "Maximum Voltage" and display it
in Putty terminal.
==========================
Note: As it must handle 4V (or higher), I set J9 of CY8CKIT-044 to 3-2 (5V)
Also in the Design Wide Resources > System
I set VDDA, VDDD, VDDIO to 5.0
schematic
Note: To test the program, I connected a POT (5.0V, P2(0), GND)
pins
ADC Configuration
main.c
===================
#include "project.h"
#include "stdio.h"
#define STR_BUF_LEN 64
char str[STR_BUF_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\r") ;
}
void init_hardware(void)
{
CyGlobalIntEnable; /* Enable global interrupts. */
UART_Start() ;
ADC_Start() ;
}
int16_t measure(void)
{
int16_t raw_count ;
int16_t mV ;
int ch = 0 ;
ADC_StartConvert() ;
ADC_IsEndConversion(ADC_WAIT_FOR_RESULT) ;
raw_count = ADC_GetResult16(ch) ;
mV = ADC_CountsTo_mVolts(ch, raw_count) ;
return( mV ) ;
}
void show_value(int16_t mV)
{
int overflow_flag = 0 ;
int negative = 0 ;
if (mV >= 4000) {
overflow_flag = 1 ;
}
if (mV < 0) {
negative = 1 ;
mV = -1 * mV ;
print("-");
}
snprintf(str, STR_BUF_LEN, "%d.%03d ", mV/1000, mV%1000) ;
print(str) ;
if (overflow_flag) {
print("Maximum Voltage") ;
}
print("\n\r") ;
}
int main(void)
{
int16_t mV ;
init_hardware() ;
splash("CY8CKIT-044 ADC Test with limit Voltage") ;
for(;;)
{
mV = measure() ;
show_value(mV) ;
CyDelay(1000) ;
}
}
===================
putty setup
putty output
moto
P.S. BTW, you could post a question/request in this Code Example Space,
then you may not have to wait for a day. (As I was taking off, yesterday)
Show LessHi all,
In order to study how to turn on and control many LEDs, I created a board with a matrix. I decided to make a roulette wheel using 36 LEDs. This time, it will be a program to test this LED display board.
The environment used is as follows:
・PSoC Creator 4.3
・CY8CKIT-044
36 LEDs are mounted on the Arduino board, and 12 GPIOs are used to configure a 6x6 matrix. The circuit looks like this:
The actual Arduino board was made as shown in the picture below. There were quite a lot of wiring and it got messed up.
The circuit creates a counter to count 6 by combining the components of Coutner and Compare in column side. It is used to select the De-Multiplexer to select the output. The row side of the LED matrix is switched half alternately after 6 counts. As a result, the lighting of the three LEDs moves to shift. This will ensure that the LED board wiring is correct. The circuit and pin layout are as follows.
Since the purpose is to check the lighting of the LED, the PWM output is set to a slow frequency with a 5KHz clock as the input.
The program just starts PWM_1.
#include "project.h"
int main(void)
{
CyGlobalIntEnable; /* Enable global interrupts. */
/* Place your initialization/startup code here (e.g. MyInst_Start()) */
PWM_1_Start();
for(;;)
{
/* Place your application code here. */
}
}
If the connection is successful, the lights will be as shown below.
Thanks,
Kenshow
Show LessHi,
Provided below is basic o-scope demo, operating in hardware triggered mode. It can be used for acquiring fast transients using PSoC5 SAR_ADC.
Two modes of operation are shown:
1. ADC is operating in free-running mode, while DMA is set to "Ready" mode, waiting for a hardware trigger. Once external trigger is detected, DMA transfers pre-defined number of points (N=200) into RAM buffer, and fires interrupt once completed.
2.. ADC is operating in clocked mode. ADC clock is first set to "Ready" mode, waiting for a hardware trigger. Once external trigger is detected, ADC starts acquiring data, which is transferred to RAM buffer by DMA. Once pre-defined number of points (N=200) has been transferred, DMA fires interrupt.
Acquired data is then being transferred by UART and plotted by external charting tool SerialPlot (by Yavuz Ozderya).
In this example, the device under test (DUT) is simply a KIT-059 onboard 2.4nF capacitor (C4), which is being charged/discharged through the digital output pin configured in Resistive Pull Up/Down mode.
As shown, ADC sampling rate is 1MHz, resolution 8-bit, N acquired points = 200. The ADC can be overclocked to about 1.7 MHz using clocked mode.
This project uses several custom Community components and libraries:
SerialPlot: SerialPlot: interface to real-time data charts
PSoC Annotation Library: PSoC Annotation Library v1.0
Yavuz Ozderya, Serial PLOT v0.10.0, https://hasanyavuz.ozderya.net/?p=244
/odissey1
Figure 1. ADC in free-running mode. DMA is h/w triggered.
Figure 2. ADC in clocked mode. DMA is clocked by ADC's end-of-sampling (eos).
Figure 3. Pulse train generator for testing. Pulse delay - 20us, pulse length - 20us, repetition - 100Hz. The DUT is KIT-059 onboard capacitor C4 (2.4nF), driven by the digital Pin_150, configured for Resistive Pull Up/Down.
Figure 4. SerialPlot custom component for plotting acquired data. configured for Simple Binary, 1-channel, uint8 data.
Figure 5. Project annotation using PSoC Annotation Library 1.0.
Figure 6. Oscilloscope traces: Yellow - DUT, Cyan - PWM pulse, Fuchsia - ADC trigger pulse.
Figure 7. SerialPlot output and DataFormat window.
Show Less
Attached below is a demo project showing RMS (Root Mean Square) measurement using weighting function technique. In such approach ADC is continuously sampling the signal, and RMS is calculated over finite interval of ~10 AC periods using a weighted window. This simple approach works if signal frequency variations are within pre-defined range, and high output rate is not needed. It can work for non-demanding application such as 50-60 Hz AC monitoring.
The idea is illustrated on Chart 1.
Chart 1. Calculated AC signal, signal squared, weighting window and their product.
AC signal simulated by the Cosine (10 periods), and weighting function by the Gaussian, calculated over 1001 points (1000 intervals).
Cosine = cos( 2 * PI * Freq * X ); Gauss = exp( -(X^2 / (2 * sigma^2) ), and where Freq = 10 and sigma = 250. The pseudocode is provided here:
Re: bounces happened at comparator output
Despite the weighting function here is being clipped, the calculated RMS = 0.707106 matches theoretical value sqrt(1/2).
The project uses double-buffering technique. The incoming AC signal is continuously sampled using PSoC5 DeltaSigma ADC (16-bit) and transferred to the ring Buffer in RAM by DMA. Once half of Buffer is filled, the interrupt is fired requesting data processing, while DMA continues to populate the Buffer in the background. RMS update frequency is defined by the size of the Buffer and ADC sampling rate. ADC sampling rate determines amount of harmonics captured, thus the accuracy of the measurements. Note that this approach does not require synchronizing the ADC sampling clock and AC signal, which makes it very simple and portable to PSoC4 and PSoC6.
Data below shown for ADC sampling rate of 2 kHz and Buffer size of 2x401 samples. Resulting RMS update rate was approx. 5 Hz. Project was also tested using other parameters: ADC-1, 2, 4, 8 kHz, 1/2 Buffer size - 201, 401 and 801 samples.
Project includes optional arbitrary signal generator, which can be safely removed if external signal generator is available. It requires following custom components:
* DDS32 v0.0 : Arbitrary frequency DDS generator. https://community.cypress.com/message/158566#158566
* WaveGen8 v0.0 (beta) : Arbitrary shape wave generator (included into this project)
* QuadDec_SW v0.1 : Quad decoder w/button switch. https://community.cypress.com/thread/30654
Other optional custom component used in the project:
* PSoC Annotation Library v1.0: https://community.cypress.com/message/204321
* StopWatch v0.0 (beta) : Timer for code profiling (included into this project)
Also attached a stripped down version of the project (without signal generator and other external components). This may help if external signal generator is available.
/odissey1
Figure 1. Project schematic.
Figure 2. Project timing diagram
Figure 3. Optional arbitrary signal generator.
Figure 4. KIT-059 Circuit diagram using PSoC Annotation Library v1.0.
Figure 5. Yellow trace - AC signal input; Cyan - signal reference; Fuchsia - RMS voltage output.
Figure 6. UART terminal output.
Show Less
Hi,
In the previous post it was shown how to use DMA with DelSig-ADC and Filter (PSoC5).
DelSig_ADC - Filter - VDAC8 streaming demo using DMA
Provided below is similar project, but utilizing ADC_SAR instead of the DelSig-ADC.
Provided below are 3 projects:
1. SAR-Filter-VDAC_01c_stripped.cydsn
Standard ADC_SAR-Filter-VDAC demo, exemplifying the ADC_SAR issues:
* ADC_SAR is not performing correctly in the differential mode. The ADC_SAR output is always unsigned (0-4095) no matter if input is configured for differential or single mode (the DelSig-ADC correctly outputs -2048 to 2047 in the differential mode).
* The Filter input expects signed 16-bit data, but ADC_SAR produces only 12-bit unsigned data. This 4-bit offset can't be corrected by DMA alone.
As a result, a simple DMA transfer ADC-Filter-VDAC results in very weak output, 1/16 of the VDAC8 full output scale.
2. SAR-Filter-VDAC_signed_FIFO_02a.cydsn
Enhanced demo, where the ADC_SAR output is first converted from unsigned to 2's compliment, and then scaled up by 4 bits to make a 16-bit signed data, which is captured by the FIFO and transferred to the Filter by DMA1. The Filter output is also signed, so it converted back to unsigned (uint8) using external logic, and transferred to VDAC using DMA2 with chained TDs.
3. SAR-Filter-VDAC_unsigned_FIFO_02a.cydsn
Simplified demo, where the ADC_SAR output is NOT converted from unsigned to 2's compliment. It is just scaled up by 3 bits to make a 15-bit unsigned data, which is captured by the FIFO and transferred to the Filter by DMA1. The filter output is UN-signed, so it can be sent directly to VDAC8 by DMA2. The Filter gain is doubled to compensate for amplitude loss.
/odissey1
Project uses several custom Community components, which are included in the project. A full version of the project has sine generator included. A stripped version of the project has sine generator removed. It can be used if external function generator is available.
* ADC_SAR_ex: Re: Best Approach: Implement DMA on 16bit Timer or 2 Status Registers? (included in the project)
* FIFOin: Re: Best Approach: Implement DMA on 16bit Timer or 2 Status Registers? (included in the project)
* BusConnect: BusConnect: virtual interface for digital hardware bus (included in the project)
* WaveGen8 (RAM-DMA-VDAC8 wave generator, included in the project)
* QuadDecoder_SW: Re: Quad Decoder with Button Switch component for rotary shaft encoders
* DDS32: Re: DDS24: 24-bit DDS arbitrary frequency generator component
* optional PSoC Annotation Library: PSoC Annotation Library v1.0
Presented Below are screenshots from the "enhanced" project SAR-Filter-VDAC_signed_FIFO_02a.cydsn
Figure 1. ADC_SAR-Filter page schematic. ADC result is converted from 12-bit unsigned to to 16-bit 2's complement. The Filter gain = 1.
Figure 2. Filter-VDAC page schematic. Filter result converted from 2's complement to 8-bit unsigned using DMA2 two chained TDs.
Figure 3. Optional signal (sine) generator for project testing. It is not included in the stripped version of the project, which requires external signal generator for testing.
Figure 4. Project annotation (made using optional PSoC Annotation Library v1.0 ). Note the ADC input bias is taken directly from the bias capacitor C12. This schematic is shared among all projects.
Figure 5. Cyan - 1 kHz ADC signal input, Yellow trace - VDAC output, Fuchsia - signal reference. Filter configured for LPF, Fc=5kHz, Gain=1.
Figure 6. Cyan - 5 kHz ADC signal input, Yellow trace - VDAC output, Fuchsia - signal reference.. Filter configured for LPF, Fc=5kHz, Gain=1.
Figure 7. Cyan - 6 kHz ADC signal input, Yellow trace - VDAC output, Fuchsia - signal reference. Filter configured for LPF, Fc=5kHz, Gain=1.
Show Less