PSoC™ 5, 3 & 1 Forum Discussions
Dithering is a widely used technique in Digital Processing where a noise is intentionally introduced into a system to increase the resolution of the system. Say we have an 8 bit DAC with a full scale value of 255mV. Each count of the DAC represents 1mV. What if we wanted an output of 1.25mV from the DAC. Switch the DAC output between 1mv and 2mV keeping the output at 2mV 25% of the time and 1mV 75% of the time, the average value of the output would be 1.25mV. For an output of 1.5mV, the DAC output should be maintained at 2mV for 50% of the time and 1mV 50% of the time.
Now let us see how this method can be implemented using the PSoC 3 hardware to create a 10 bit DAC.
Place an 8 bit voltage DAC. Select 1.020V (4mV / bit) as the range. Set the Data_Source to “DAC Bus” and Strobe_Mode to “External”. The output of the DAC can now be controlled using an 8 bit data bus and the output will be updated on the rising edge of the Strobe input.
Place a Multiplexer from the Digital >> Logic category. Set number of input terminals to 2 and terminal width to 8. The multiplexer can now switch between two 8 bit data buses. Place two control registers from the Digital >> Registers category. Set the number of outputs to 8. Connect the 8 bit data bus of the Control registers to the input of the Multiplexer.
Place a PWM, with a period of 3 and compare type set to “Less than”. The output of the PWM now can be controlled to 0%, 25% and 75% duty cycle. Connect the output of the PWM to the control input of the Mux. Use the same clock of the PWM as a strobe to the DAC. The hardware is now ready.
In firmware, write the Most Significant 8 bits of the 10 bit DAC value to the ControlRegister0 and one count higher value to ControlRegister1. Use the Least Significant 2 bits to update the PWM’s pulse width. Now, the PWM switches the input of the DAC between the two 8 bit Control Register values and the average output of the DAC would be our 10 bit DAC result. Use an external Low Pass filter to remove the switching frequency. As the switching frequency is at 125KHz, a simple RC filter will do the trick. Below is the code.
void main()
{
uint16 DacValue;
VDAC8_Start();
PwmMsb_Start();
Amplifier_Start();
for(;;)
{
DacMsbReg0_Write(DacValue >> 2);
DacMsbReg1_Write((DacValue >> 2) + 1);
PwmMsb_WriteCompare((uint8)(DacValue & 0x03));
}
}
The range of the DAC now is 0 to 1020 counts; each count representing 1mV, subject to some offset and gain error inherent in the 8 bit DAC.
Show LessI've compiled the UART_Rx.cywrk example in the CY8CKIT-001 development kit and have been unable to get it working while sending characters over RS232 using Labview. I've send "LCD". It shown double alpla and japan character. Even I use hyperterminal also same. Any ideas what might be causing the problem?? Thanks.
Show LessWith a handful of PSoC3 resources and an external capacitor, a Voltage controlled oscillator can be created.
Pin "Cint" is configured as both Digital and Analog pin with a drive mode Open Drain drives low. When output of Comparator is High, IDAC output is connected to the pin. When comparator output is Low, the pin shorts to Ground.
IDAC – configured as a source – charges an external capacitor connected to "Cint". When the capacitor voltage crosses input voltage Vin, comparator output becomes low (comparator is set for inverted logic) and discharges the capacitor. As capacitor voltage becomes zero, the comparator output becomes high and IDAC starts charging the capacitor. The cycle continues and we get an oscillator whose frequency is inversely proportional to Vin. The circuit has excellent “Period vs. Vin” linearity.
For a given input voltage, the combination of IDAC value and external capacitor determines the maximum Period (1/f) of the output. We know that when a capacitor is charged using a constant current, the time taken to charge to a known voltage is
t = C * V / I
For example, if the maximum period value is desired to be 500uS for an input voltage of 2.5V, for an IDAC value of 1uA, the value of C can be calculated:
C = (500uSec * 1uA) / 2.5V = 200pF
The comparator is synchronized to a clock. The period of the clock should be long enough to discharge the capacitor. Too high a clock frequency, the capacitor may not discharge completely. Too low a clock frequency, the % of the "discharge time" to "charge time" will increase and will reduce the linearity. The value of the clock will also depend on the value of the capacitor. Higher value of capacitor will require a longer discharge time.
Selecting the right combination of IDAC, Capacitor and the SyncClock is an interesting exercise left to the user. Show Less
I have seen customers doing mistake when connecting a negative signal to PSoC. Since, PSoC works only on positive supply, so negative signal can not be connected directly to any of the digital or analog block.
There is a very nice blog written by Ganesh Raaja on how to measure Negative Voltage using PSoC1, it can be accessed using this link: http://www.cypress.com/?rID=50815&cache=0
Happy working with PSoC.
Best regards,
Pushek
Show LessHello,
I'd like to implement three bandpass filters with the CY8CKIT-001 PSOC DEVELOPMENT Kit. I read some information about PSoc filters into the forum and I read the AN2099 application note too, but I'm still not sure that they can be implemented and how would can I do it.
The filter's characteristics are:
Filter1: Fs=105Hz Fi=45Hz B=60Hz Fr=68,7Hz Q=1,14
Filter2: Fs=145Hz Fi=65Hz B=80Hz Fr=97Hz Q=1,21
Filter3: Fs=8Hz Fi=0,5Hz B=7,5Hz Fr=2Hz Q=0,26
If it is really possible to implement these kind of filters, what would be the best method, using DBF blocks, SC/CT o FIR filters?.
Best regards,
Antonio M.
Show LessHi,
I have to write software for psoc 3 which is going to sleep (~uA consumption) for dozen of milliseconds, few times per second. Each time it has to be different value of sleep time.
I'm was surprised that i'm expecting some many problems with such case in PSoC3...
my program should looks like this(pseudo code):
while(1){
GoToSleepFor(5ms)
DoSomething()
GoToSleepFor(100ms)
DoSomething()
GoToSleepFor(1ms)
DoSomething()
GoToSleepFor(800ms)
DoSomething()
}
Problem is with CyPmSleep which:
1. It does not accept any other delay then power of 2 (2,4,8,16ms..etc)
2. When I mix different intervals i need to wait more or less one interval to be sure that next, same interval will be fine (as it's written in system documentation). Documentation is right - when i'm mixing intervals then times are way different than it is expected.
RTC can be used only for intervals >1second.
Is there no way of doing this?!
I was thinking about putting an extra timer (internal) into psoc and connect it to 32kHz clock from external oscillator but i dont know how to make it work during sleep:
1.timer would have to work when everything else is sleeping (~uA consumption)
2.somehow signal from this timer has to wakeup psoc3.
Other workaound is to always go to sleep for 2ms.Sometimes for hundreads of times - 400x when i want to sleep 900ms. But this doesnt look like proper way of doing it.
ps. using externals signals or devices to wake up is not accpetable...
ps2. its battery powered and every uA counts.
I would appreciate some advice/hint
Thank You in advance for reply!
Show LessHi,
I am having difficulty implenting low power modes combined with using the FreeRTOS platform and the PSoC 5. Specifically, UART comms are getting corrupted.
I have a task which receives messages to send to the UART. When it receives a message, it prevents the uC from sleeping, wakes the uart up, and then sends the message using the API (Uart_PutSring()). It then waits until the message is sent before allowing the micro to sleep and sleeping the uart itself.
Some messages are getting through un-corrupted, others are a horrible mess...
Here is a code snippet of the UART task...
//! @brief Main debug uart task
//! @param *pvParameters Void pointer (not used)
//! @note Not thread-safe. Do not call from any task, this function is a task that
//! is called by the FreeRTOS kernel
//! @public
void vDebugUart_MainTask(void *pvParameters)
{
// Sleep uart
UART_DEBUG_Sleep();
uint8 *message;
for(;;)
{
// Wait for a message pointer to arrive in the queue
xQueueReceive(xDebugUartTxQueue, &message, portMAX_DELAY);
#if(DEBUG_LEDS == 1)
DebugUart_FlashLed();
#endif
// Message must of been received, so now prevent micro from sleeping and send
PowerMgmt_SleepLock();
// Wakeup UART
UART_DEBUG_Wakeup();
UART_DEBUG_PutString(message);
//vTaskDelay(200/portTICK_RATE_MS);
// Wait until UART has completely finished sending the message
// (both the hardware buffer and the byte sent flag are set)
while(!(UART_DEBUG_ReadTxStatus() & (UART_DEBUG_TX_STS_FIFO_EMPTY | UART_DEBUG_TX_STS_COMPLETE))); //(software wait)
//while(!(UART_DEBUG_ReadTxStatus() & UART_DEBUG_TX_STS_COMPLETE));
// Sleep uart
UART_DEBUG_Sleep();
// Now it is safe to unlock the micro to allow for sleeping
PowerMgmt_SleepUnlock();
// Finished, now loop for next message
}
}
Cheers, Geoff
Show Less