Connecting Waveshare High-Precision AD/DA Board (ADS1256) to DE10-Nano Kit - c

I'm currently working on an ECG project and I'm having some difficulties using the Waveshare High-Precision AD/DA Board (which has an ADS1256 ADC and is meant for use with RPI) with the Terasic DE10-Nano Kit.
I'm using an Altera SPI Master peripheral in Qsys with the following settings:
SCLK rate: 20000
Data Width: 8 bits
Shift Direction: MSB first
Clock Polarity: 0
Clock Phase: 1
No synchronizer stages
For the remaining required signals I'm using Avalon PIO:
DRDY (Input)
RST (output)
PWR (output)
Additionally, there's a Nios2 CPU which makes use of alt_avalon_spi_command to send SPI commands and IOWR_ALTERA_AVALON_PIO_DATA to control the PIO.
The issue I'm experiencing, is that the DRDY signal is never asserted (it's expected to go LOW before being able to read data). I understand this signal should be used with a pull-up resistor; I've tried the following, neither of which worked:
Configure internal pull up on DE10-Nano GPIO pin
Use external pull up resistors (10K/56K)
I understand I should be able to read the Chip ID of the ADS1256, prior to configuring it. I first reset the device, as per:
https://github.com/waveshare/High-Precision-AD-DA-Board/blob/master/Jetson%20nano/ADS1256/C/obj/ADS1256.c#L39
/* RESET */
IOWR_ALTERA_AVALON_PIO_DATA( WAVESHARE_ADS_RST_BASE, HIGH );
usleep(200);
IOWR_ALTERA_AVALON_PIO_DATA( WAVESHARE_ADS_RST_BASE, LOW );
usleep(200);
IOWR_ALTERA_AVALON_PIO_DATA( WAVESHARE_ADS_RST_BASE, HIGH );
Then I wait for DRDY to go LOW and this never seems to happen, regardless of the above-mentioned setup for the pull up resistor:
alt_u8 ADS1256_wait_DRDY( void ) {
for( int i=0; i<50; i++ ) {
alt_u8 drdy = ADS1256_DRDY_get_level();
if ( drdy == LOW ) {
printf( "DRDY asserted\n" );
return 0;
} else {
usleep( DELAY_DRDY );
}
}
printf( "Timeout: DRDY not asserted.\n" );
return -1;
}
I'm probing using a Hobby Components Logic Analyser. The pin connections are elaborated below:
AD/DA RPI PIN DE10-Nano Location Standard HDL Signal Direction Logic Analyzer
==========================================================================================================
3v3 3v3 3v3
GND GND GND
MOSI 19 (GPIO 10) GPIO_0(0) PIN_V12 3.3V LVTTL SPI_MOSI OUT D0
MISO 21 (GPIO 9) GPIO_0(2) PIN_W12 3.3V LVTTL SPI_MISO IN D1
SCK 23 (GPIO 11) GPIO_0(4) PIN_D8 3.3V LVTTL SPI_SCK OUT D2
P3 (CS_PIN) 15 (GPIO 22) GPIO_0(1) PIN_E8 3.3V LVTTL SPI_SS_n(0)* OUT D3
P1 (RST) 12 (GPIO 18) GPIO_0(3) PIN_D11 3.3V LVTTL ADS_RST OUT D4
P0 (DRDY) 11 (GPIO 17) GPIO_0(6) PIN_AE15 3.3V LVTTL WAVESHARE_DRDY IN D5
The logic analyser output is as following:
PulseView
Any help on how to set this up is much appreciated. Apologies if my post is not great, I'm fairly new to posting on these forums.

Some of the pin assignments were not correct. After fixing these and testing with a different microcontroller instead of the AD/DA board, the DRDY is asserted, but the issue persists with the waveshare board. It looks like a board specific issues, so I've contacted the manufacturer for assistance.

Related

What Prescaler and Counter Period (AutoReload Register) in Timer with PWM generation in STM32CubeIDE should I set to control a DC motor?

I am a begginer in STM. I have STM32 NUCLEO-F411RE, Pololu 1570 6V 2220RPM DC Motor, L298N DC Motor Driver and 6V 1,3Ah Xtreme Acumulator. I want my motor to be just rotating for example with 80% duty cycle pwm. I have it connected as in this picture:Here is picture of my connection
But instead of 2 motors I have one and instead of Arduino I have STM. In my case pin ENA from motor driver is connected to PB6 pin where I set TIM4 with Channel 1 PWM generation. And IN1 pin from motor driver is connected to PA11 and IN2 to PA12. Here is the code which I add by myself to main():
/* USER CODE BEGIN 2 */
HAL_GPIO_WritePin(GPIOA,Dir1_Pin,GPIO_PIN_SET); // Start motor clock wise rotation, Dir1_Pin is PA11 and Dir2_Pin is PA12
HAL_GPIO_WritePin(GPIOA,Dir2_Pin,GPIO_PIN_RESET);
HAL_TIM_Base_Start(&htim4);
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
htim4.Instance->CCR1=????; //What number should I put here to have my motor rotating with 80% duty cycle?
}
/* USER CODE END 3 */
}
I have already been looking for explanations on the internet, make calculations for a week, but didn't find anything which would work for my case. Red light on motor driver is lighting. With some of results from my calculations it was making a "tick tick" sound, but the motor was not rotating. I do not know exactly what values can be send to ENA Pin for my specific DC motor.
Duty cycle is just a high-to-low ratio of the PWM clock.
To calculate value of CCR, you have to know PWM length in timer clocks, that is usually set up in ARR, that is mapped to Init.Period structure member:
void PWM_SetDutyCycle(uint16_t dc_percent) {
// recalculate into pulse width
uint16_t dc = htim1.Init.Period * ((uint32_t)dc_percent) / ((uint32_t) 100);
htim4.Instance->CCR1 = dc;
}

STM32 maximum interrupt handling frequency

I am trying to implement my own SPI communication from FPGA to STM in which my FPGA serve as MASTER and generate Chip enable and clock for communication. FPGA transmit data at its rising edge and receive data at its falling edge my FPGA code works properly.
In STM side i capture this master clock on interrupts and receive data at its rising edge and transmit at its falling edge but communication not work properly if i increase clock speed from 250khz
According to my understand STM work at 168 Mega hz i set clock setting according to 168Mhz and handling of 1mhz interrupt is not a big problem so can you any guide how i handle this high speed clock in STM
My code is written below
/*
* Project name:
EXTI_interrupt (EXTI interrupt test)
* Copyright:
(c) Mikroelektronika, 2011.
* Revision History:
20111226:
- Initial release;
* Description:
This code demonstrates how to use External Interrupt on PD10.
PD10 is external interrupt pin for click1 socket.
receive data from mosi line in each rising edge.
* Test configuration:
MCU: STM32F407VG
http://www.st.com/st-web-
ui/static/active/en/resource/technical/document/datasheet/DM00037051.pdf
dev.board: EasyMX PRO for STM32
http://www.mikroe.com/easymx-pro/stm32/
Oscillator: HSI-PLL, 140.000MHz
Ext. Modules: -
SW: mikroC PRO for ARM
http://www.mikroe.com/mikroc/arm/
* NOTES:
receive 32 bit data from mosi line in each rising edge
*/
//D10 clk
//D2 ss
//C0 MOSI
//C1 FLAG
int read=0;
int flag_int=0;
int val=0;
int rec_data[32];
int index_rec=0;
int display_index=0;
int flag_dint=0;
void ExtInt() iv IVT_INT_EXTI15_10 ics ICS_AUTO {
EXTI_PR.B10 = 1; // clear flag
flag_int=1; //Flag on interrupt
}
TFT_Init_ILI9340();
void main() {
GPIO_Digital_Input(&GPIOD_BASE, _GPIO_PINMASK_10);
GPIO_Digital_Output(&GPIOD_BASE, _GPIO_PINMASK_13); // Set PORTD as
digital output
GPIO_Digital_Output(&GPIOD_BASE, _GPIO_PINMASK_12); // Set PORTD as
digital output
GPIO_Digital_Output(&GPIOD_BASE, _GPIO_PINMASK_14); // Set PORTD as
digital output
GPIO_Digital_Output(&GPIOD_BASE, _GPIO_PINMASK_15); // Set PORTD as
digital output
GPIO_Digital_Input(&GPIOA_IDR, _GPIO_PINMASK_0); // Set PA0 as
digital input
GPIO_Digital_Input(&GPIOC_IDR, _GPIO_PINMASK_0); // Set PA0 as
digital input
GPIO_Digital_Input(&GPIOC_IDR, _GPIO_PINMASK_2); // Set PA0 as
digital input
GPIO_Digital_Output(&GPIOC_IDR, _GPIO_PINMASK_1); // Set PA0 as
digital input
//interupt register
SYSCFGEN_bit = 1; // Enable clock for alternate pin
functions
SYSCFG_EXTICR3 = 0x00000300; // Map external interrupt on PD10
EXTI_RTSR = 0x00000000; // Set interrupt on Rising edge
(none)
EXTI_FTSR = 0x00000400; // Set Interrupt on Falling edge
(PD10)
EXTI_IMR |= 0x00000400; // Set mask
//NVIC_IntEnable(IVT_INT_EXTI15_10); // Enable External interrupt
while(1)
{
//interrupt is not enable until i push the button
if((GPIOD_ODR.B2==0)&&(flag_dint==0))
{ if (Button(&GPIOA_IDR, 0, 1, 1))
{
Delay_ms(100);
GPIOC_ODR.B1=1; //Status for FPGA
NVIC_IntEnable(IVT_INT_EXTI15_10); // Enable External interrupt
}
}
if(flag_int==1)
{
//functionality on rising edge
flag_int=0;
if(index_rec<31)
{
//display data on led
GPIOD_ODR.B13= GPIOC_IDR.B0;
//save data in an array
rec_data[index_rec]= GPIOC_IDR.B0;
//read data
index_rec=index_rec+1;
}
else
{
flag_dint=1;
NVIC_IntDisable(IVT_INT_EXTI15_10);
}
} // Infinite loop
}
}
Without getting into your code specific, see PeterJ_01's comment, the clock rate problem can be explained by a misunderstanding of throughput in your assumtions.
You assume that given that your STM device has a clock of 168Mhz it can sustain the same throughput of interrupts, which you seem to have conservatively relaxed to 1Mhz.
However the throughput of interrupts it will be able to support is given by the inverse of the time it takes the device to process each interrupt. This time includes both the time the processor takes to enter the service routing (ie detect the interrupt, interrupt the current code and resolve from the vector table where to jump to) plus the time taken to execute the service routine.
Lets be super optimistic and say that entering the routine takes 1 cycle and the routing itself takes 3 (2 for the flags you set and 1 for the jump out of the routine). This gives 4 cycles at 168Mhz is 23.81ns, taking the inverse 42Mhz. This can also be computed by dividing the maximum frequency you would achieve (168Mhz) by the number of cycles spent processing.
Hence our really optimistic bound is 42Mhz, but realistically will be lower. For a more accurate estimate you should test your implementation timings and dig into your device's documentation to see interrupt response times.

Smartfusion2 MSS SPI communication

I am working with the Microsemi Smartfusion2 development kit from Arrow. It uses the Smartfusion2 M2S010-FG484 FPGA. (https://www.arrow.com/en/products/sf2plus-dev-kit/arrow-development-tools)
I am new to the Smartfusion2, I am trying to establish a connection between the Smartfusion2 FPGA and Arduino using the microcontroller subsystem (MSS) and programing ti in Softconsole. The problem is that I can't seem to get it to work. While trying to debug, I attached an LED (i had to improvise since I don't have an oscilloscope) to pin 3 of the arduino connector (J2) on the development board. This pin should contain the slave select 3 (pin J18 on the FPGA) as indicated in the datasheet on page 16 (https://static4.arrow.com/-/media/images/part-detail-pages/sf2-plus/new-sf2-files/sf2plus_user_guide_v1p1.pdf?la=zh-cn) and in the I/O editor of Libero SoC.
With the following code I am trying to toggle the LED/Select and deselect the specified slave (Slave 3). But nothing happens. The Slave select is active low but the LED is always on and never turns off.
/*
* main.c
*
* Created on: Aug 16, 2017
*/
#include "drivers/mss_gpio/mss_gpio.h"
#include "drivers/mss_spi/mss_spi.h"
#include <stdio.h>
/*Delay function in milliseconds, for 100MHz clock*/
void Delay(uint32_t Delayms){
uint32_t i = 0;
uint32_t DelayValue = Delayms*2000; //1000ms*100000 = 100000000 (100MHz)
for(i = 0; i <= DelayValue; i++){
}
}
/*Configuration for SPI0*/
void ConfigSPI1(void){
/*Initialize and Configure SPI1*/
MSS_SPI_init(&g_mss_spi1);
MSS_SPI_disable(&g_mss_spi1); //Disable SPI1
/*Configure SPI1 as master, protocol mode, clk speed, frame size*/
MSS_SPI_configure_master_mode(
&g_mss_spi1, //Selects SPI1 for configuration
MSS_SPI_SLAVE_3, //Set the target device as slave 3
MSS_SPI_MODE2, //Serial peripheral interface operating mode
64u, //Divider used on APB bus (PCLK) clock in order to generate the SPI clock
12); //Number of bits making up the frame, max = 32
MSS_SPI_enable(&g_mss_spi1); //Enable SPI1
}
/*SPI0 test function*/
void SPI1Test(void){
MSS_SPI_set_slave_select(&g_mss_spi1, MSS_SPI_SLAVE_3); //Used by a MSS SPI master to select a specific slave
MSS_SPI_transfer_frame(&g_mss_spi1, 0xaaa); //Transfers "0xaaa" to the selected slave (slave 3)
Delay(1000); // I used this delay for testing, to keep the SS low for a longer time to be able to see the LED turn off
MSS_SPI_clear_slave_select(&g_mss_spi1, MSS_SPI_SLAVE_3); //Used by a MSS SPI master to deselect a specific slave
}
int main(){
/*Configure modules*/
ConfigSPI1();
/*Infinite loop*/
for(;;){
SPI1Test();
Delay(3000);
}
return 0;
}
Does anyone see a mistake in my code that might be causing the problem? or maybe have an working example code for me?
I wrote another program to toggle pin J18/the slave select 3 pin with the gpio driver, and that worked, it toggled the LED. I am also pretty certain that the design in Libero SoC is correct and imported correctly.
Thank you for your time!

Controlling a servo with raspberry pi using the hardware PWM with wiringPi

I tried controlling the servo with softPwm using the wiringPi Library but this made the servo stutter.
Therefore I want to use the hardware PWM pin on the Raspberry Pi (GPIO18) with the wiringPi library.
But I don't understand how to set the frequency to 50 Hz and change the duty cycle to have a pulse width ranging from 0.8 ms to 2.5 ms.
I found the following relationship on the internet (i dont know if it is correct):
pwmFrequency in Hz = 19.2e6 Hz / pwmClock / pwmRange.
i know the clock divisor max value is something around 4000 and the Raspberry Pi PWM clock has a base frequency of 19.2 MHz. so this gives me ~4,8KHz.
i already got these settings which should give me ~50Hz using the following relationship:
//put PWM in mark-space mode, which will give you
//the traditional (and easily predictable) PWM
pwmSetMode(PWM_MODE_MS);
//setting ping GPIO 18 as a pwm output
pinMode(18,PWM_OUTPUT);
//Set clock divisor to 4000
pwmSetClock(4000);
pwmSetRange (10) ;
I dont got a oscilloscope to test the output signal to check what setting changes what. this makes it hard to find it out myself.
Long story short:
Can anyone tell me how I can achieve a duty cycle with a pulse width of 0,8ms to 2,1ms for controlling a servo using the hardware PWM on the Raspberry Pi.
I'm a complete newby to Pi and to Servo's. But I got it to work with wiringPi.
It says here that we're looking to create pulse of 1ms to 2ms in length, every 20ms or so. Assuming this 19.2Mhz base clock is indeed correct, setting pwm clock to 400 and pwm range to 1000, should give a pulse at 48Hz or every 20.8 ms. Then setting pwm value to 48 should give you a 1ms long pulse and a pwm value of 96 should give you a 2ms long pulse.
But you need to set the chip in pwm-ms mode.
(Lots of shoulds here, since I do not have an osciolloscope either)
So to set it up:
gpio mode 1 pwm
gpio pwm-ms
gpio pwmc 400
gpio pwmr 1000
And then you can turn the servo from left to right via
gpio pwm 1 48
gpio pwm 1 96
(Actually, the servo I got worked from 28 up to 118; could be the servo)
(The setup sequence seems important; could be a bug)
if (wiringPiSetup () == -1) //using wPi pin numbering
exit (1) ;
pinMode(1, PWM_OUTPUT);
pwmSetMode(PWM_MODE_MS);
pwmSetClock(384); //clock at 50kHz (20us tick)
pwmSetRange(1000); //range at 1000 ticks (20ms)
pwmWrite(1, 75); //theretically 50 (1ms) to 100 (2ms) on my servo 30-130 works ok
return 0 ;
Make sure you are using correct gpio pins!
Models A and B have one hardware PWM on pin 18 BCM (1 wPi).
Models A+ and B+ can output second hardware pwm on pins 13 and 19 BCM (23, 24 wPi)
How about using RPIO instead? Here's the link to the library: http://pythonhosted.org/RPIO/index.html
Here's the PWM example: http://pythonhosted.org/RPIO/pwm_py.html
And you may also use the C source directly: https://github.com/metachris/RPIO/tree/master/source/c_pwm
I got wiringPi to do it through software bit-banging. I might have tried RPIO but my particular application requires that the audio output works, and I understand that RPIO's DMA makes audio go away. I might have also tried wiringPi's softPwm or even softServo, but I also require to run a DC motor through PWM, and I don't want to bring the whole system down to 50Hz just for the servo.
This program worked as a demonstration, has no jitter (because it doesn't continuously drive the positioning pulses), and lands on its target each time with a visibly indistinguishable error. Granted the Pi isn't doing much else at the time to interfere with the program's timing (except running an X server through SSH, gedit, terminal session, everything in top, etc.).
// Servo trial 11/15/14 by SLC
#include <wiringPi.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
wiringPiSetup();
pinMode( 6, OUTPUT );
digitalWrite( 6, HIGH );
int idx = 0, tries = 0;
while ( tries++ < 30 )
{
int i;
const int period[] = { 500, 1500, 2500 };
printf( "Setting period to %i ms\n", period[idx] );
for ( i = 0; i < 20; ++i )
{
// Output going through an inverter (to convert 3.3V to 5V)
digitalWrite( 6, LOW );
usleep( period[idx] );
digitalWrite( 6, HIGH );
usleep( 20 * 1000 );
}
++idx;
idx %= 3;
sleep( 2 );
}
}
My servo is a Radio Shack Micro Servo, which appears identical to the other "micro" servos out there. I also found I could ditch the inverter and just drive the signal using the 3.3V GPIO.

SPI master to PIC18F4550 slave synchronization (C18) using NETMF

A .NET Micro Framework device (ChipworkX in this case) sends a byte through the SPI interface to a PIC18F. Having PIE1bits.SSPIE enabled, the following code is executed on interrrupt:
void high_isr (void)
{
PIE1bits.SSPIE = 0;
PIR1bits.SSPIF = 0; //Clear interrupt flag.
LATDbits.LATD5 = 1; //Enables LED for high interrupt activity.
while ( !SSPSTATbits.BF ); //Wait until cycle complete
red_byte_array[1] = SSPBUF;
SSPBUF = 0x00;
LATDbits.LATD5 = 0;
PIE1bits.SSPIE = 1;
}
When sending the same byte a few times, the data does not seem to be read consistently. Both master and slave are setup for clock idle low level, and data clocking on rising edge. I don't use the chip select line, because it's direct communictation.
Finally, the master sends data at 100 kHz, while the PIC is operating at 8 MHz.
How do I improve and/or fix this code?
On the PIC16F886/7:
If you are not using the /SS, then the data changes on the rising edge and is sampled on the falling edge, for a SCK idling at 0: CKE = 0, CKP = 0 (or 1), SMP = 0.
The byte moving from the shift register to the buffer register causes BF bit and SSPIF the interrupt, so you don't normally loop about in the interrupt waiting for BF.
There should not be any need to disable SSP interrupts (SSPIE = 0), but you probably need to clear the SSPIF before returning from interrupt.
I would guess you should, on SSP interrupt (SSPIF = 1):
red_byte_array[x] = SSPBUF
SSPIF = 0
You may need to check WCOL and SSPOV for errors.
Given that your PIC only has ( 8 MHz / 100 kHz ) 80 cycles to respond, that Delay1KTCYx() seems rather long.

Resources