Thursday, June 11, 2015

MATLAB Test for Function Generator

We outputted a sine wave from the function generator at 9Hz and came up with the following plots using the following MATLAB code:

x = [
5333

55354

52449

6093

32767

32767

32767

8453

55195

52430

7259

32767

32767

32767

7356

55003

52422

8294

32767

32767

32767

6573

54890

52453

9227

32767

32767

32767

5892

54785

52461

9899

32767

32767

32767

5232

54684

52454

10570

32767

32767

32488

4680

54588

52451

11259

32767

32767

31989

4065

54512

52494

11959

32767

32767

31536

3527

54430

52537

12559

32767

32767

31071

2980

54343

52575

13303

32767

32767

30446

2162

54228

52639

14426

32767

32767

29509

1061

54059

52807

15771

32767

32767

28598

46

53948

53083

17019

32767

32767

27629

64459

53802

53489

18242

32767

32767

26818

63590

53675 ]

t=linspace(0,.00004,100);
f=1./t
figure(1)
plot(t,x)

z=fft(x)
figure(2)
plot(f,z)



***The time interval is certainly incorrect for the values shown in figure 1 (amplitude vs. time)***

 *** We expect one large peak for the plot of the FFT of the array x. This is because an FFT transforms a function from time space into frequency space to show amplitude as a function of frequency.
The next goal in the process is to have the SDK code include lines that perform the FFTs directly in the hardware of the Zedboard, eliminating the use for a computer. The results of these can be used/combined for further analysis.

Wednesday, June 10, 2015

Angle Encoder Code for Viper Motors

//From bildr article: http://bildr.org/2012/08/rotary-encoder-arduino/

//these pins can not be changed 2/3 are special pins
//CLK to pin 3
//DT to pin 2
//SW to pin 4
int encoderPin1 = 2;
int encoderPin2 = 3;
int encoderSwitchPin = 4; //push button switch
float angle;

volatile int lastEncoded = 0;
volatile long encoderValue = 0;

long lastencoderValue = 0;

int lastMSB = 0;
int lastLSB = 0;

void setup() {
  Serial.begin (9600);

  pinMode(encoderPin1, INPUT);
  pinMode(encoderPin2, INPUT);

  pinMode(encoderSwitchPin, INPUT);


  digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
  digitalWrite(encoderPin2, HIGH); //turn pullup resistor on

  digitalWrite(encoderSwitchPin, HIGH); //turn pullup resistor on


  //call updateEncoder() when any high/low changed seen
  //on interrupt 0 (pin 2), or interrupt 1 (pin 3)
  attachInterrupt(0, updateEncoder, CHANGE);
  attachInterrupt(1, updateEncoder, CHANGE);

}

void loop(){
  //Do stuff here
  if(digitalRead(encoderSwitchPin)){
    //button is not being pushed
  }else{
    //button is being pushed
    encoderValue=0;
  }
 
  angle=encoderValue*4.5;
  Serial.print(encoderValue);
  Serial.print(" ");
  Serial.print("Angle=");
  Serial.println(angle);
  //delay(100); //just here to slow down the output, and show it will work  even during a delay
}


void updateEncoder(){
  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit

  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;
   
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;
  lastEncoded = encoded; //store this value for next time


}

June 10 - Code that reads in signal from function generator



/* Input is on pin 3.  The program reads 8 bits of data sequentially and stores them as an 8 bit value.
The process of storage is shown using the LEDs.  Each bit is shifted to the left.  This is a program to
understand the bit-bang process and how the Maxim Integrated 11205 ADC works.*/

/* Include Files */
#include "xparameters.h"
#include "xgpio.h"
#include "xstatus.h"
#include "xil_printf.h"
#include "time.h"

/* Definitions */
#define GPIO_DEVICE_ID  XPAR_AXI_GPIO_0_DEVICE_ID /* GPIO device that LEDs are connected to */
#define LED 0xFC          /* Initial LED value - XX0000XX */
#define PMOD 0xFC         /* Initial LED value - XX0000XX */
#define LED_DELAY 100000000       /* Software delay length */
#define LED_CHANNEL 1        /* GPIO port for LEDs */
#define PMOD_CHANNEL 1        /* GPIO port for PMODs */
#define printf xil_printf       /* smaller, optimised printf */
#define PMOD_JA1_DEVICE_ID  XPAR_AXI_GPIO_1_DEVICE_ID
#define ABOUT_ONE_SECOND 74067512      //!< approx 1 second delay when used as argument with function delay(numberCyclesToDelay)
// Update this if uBlaze/Zynq CPU core frequency is changed, or if the external memory timing changes.
// Although emprirically tested to 1.0000003 seconds, it is not meant to be used for precise timing purposes

/* Definitions */
#define CLOCK_on 0x08    //high for the clock
#define DATAREADY_high 0x04   //high for data ready pin 3


XGpio Gpio, GpioP;           /* GPIO Device driver instance */





u32 LEDOutputExample(void)
{


 volatile int Delay;
 int Status;
 int led = LED; /* Hold current LED value. Initialise to LED definition */
 int pmod = PMOD;
 int WritetoLEDs;
 int i;
 u32 x;
 u8 uchPortWriteData=0;
 u8 uchPortReadData=0;
 u32 adcValue=0;


 int nClockCount;
 int uchUseCalibrationMode=0;

  /* GPIO driver initialisation */
  Status = XGpio_Initialize(&Gpio, GPIO_DEVICE_ID);
  if (Status != XST_SUCCESS) {
   return XST_FAILURE;
  }
  Status = XGpio_Initialize(&GpioP, PMOD_JA1_DEVICE_ID);
   if (Status != XST_SUCCESS) {
    return XST_FAILURE;
  }

  /*Set the direction for the LEDs to output. */
  XGpio_SetDataDirection(&Gpio, LED_CHANNEL, 0x00);


  /*Set the direction for the PMod - pin 3 is an input, rest are outputs. */
    XGpio_SetDataDirection(&GpioP, PMOD_CHANNEL, 0x04);

    //WritetoLEDs =0x01;
    //for(i =1;i<8;i++){
      //XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, WritetoLEDs);
       // delay(ABOUT_ONE_SECOND/3);
       // WritetoLEDs=(int)(1<<i);
   // }


  //  printf("Ready to receive.\n \r");
    //delay(10);
    //XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0xFF);

   // XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0x00);

    // First, set the clock and data lines low, and the SS# line high
            // GPIO[3:0] = {SCK, CLR#, MOSI, SS#} // default 'off' is 4'b0101 = 0x05
        //delay(10);
        uchPortWriteData = 0;
        XGpio_DiscreteWrite(&GpioP, 1, uchPortWriteData);  // The (1) means write to the only port (#1) on the uBlaze GPIO port
        //delay(10);

        // Wait until RDY# goes high
        //uchPortReadData = XGpio_DiscreteRead(&GpioP,1);
        uchPortReadData=0;
        while((uchPortReadData & DATAREADY_high)==0x00)  // keep looping while low
        {
            uchPortReadData = XGpio_DiscreteRead(&GpioP,1);
        }

        // Now, wait until RDY# goes low
        uchPortReadData = XGpio_DiscreteRead(&GpioP,1);
        while((uchPortReadData & DATAREADY_high)==DATAREADY_high)
        {
            uchPortReadData = XGpio_DiscreteRead(&GpioP,1);
        }
 for(i=15;i>=0;i--)
    {
        // Send clock high
        uchPortWriteData |= CLOCK_on;
        XGpio_DiscreteWrite(&GpioP, 1, uchPortWriteData);

       // delay(10);  // small delay, then read
        uchPortReadData = XGpio_DiscreteRead(&GpioP,1);
        //delay(10);
        // Shift the GPIO read data to the lowest bit, mask off all the other bits, then shift i (15:0)
        // number of bits to set the appropriate bit in the
        if(((uchPortReadData >> 2) & 0x01)==0x01) // the serial bit is a one, set the bit
        {
            if(i==15)
                adcValue = 0x8000;  // extend the sign of the 2s complement number to bits 31..16, and set bit 15 = 1
            else
                adcValue |= (int)(1 << i);  // bit shift
        }
        uchPortWriteData &= ~CLOCK_on;// Clock in data via negative edge
        XGpio_DiscreteWrite(&GpioP, 1, uchPortWriteData);
      //  delay(10);
       // XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, adcValue);


        //printf("The Value  %d \n \r", adcValue);

        //storedValues[i]= adcValue;
    }
  
 // The 11205 device requires 25 clocks total to complete a read.
     // We have already sent (16) clocks, so send 9 more clocks.
     // (If self-calibration mode set then we send 10 more clocks.)
     if(uchUseCalibrationMode==1)
         nClockCount = 9;
     else
         nClockCount=9;
     for(i=nClockCount;i>=0;i--)
     {
         // Send clock high
         uchPortWriteData |= CLOCK_on;
         XGpio_DiscreteWrite(&GpioP, 1, uchPortWriteData);

         //delay(10);  // small delay, then read
         uchPortWriteData &= ~CLOCK_on;// Clock in data via negative edge
         XGpio_DiscreteWrite(&GpioP, 1, uchPortWriteData);
         //delay(10);
     }



      //printf("The ADC Value  %d \n \r", adcValue);

      //XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0x01);
     // sleep(1);
     // XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0x00);
      //sleep(1);



  return adcValue; /* Should be unreachable */
}



void delay(int nStopValue)
/**
* \brief       Loop for nStopValue iterations to provide a delay.
* \par         Details
*              It is commonly used with the constant 'ABOUT_ONE_SECOND' defined in maximPMOD.h for
*              setting approximate delays
*
* \param[in]   nStopValue    - number of iterations to loop
*
* \retval      None
*/
{
    int i=0;
    int a=0;

    for(i=0;i<nStopValue;i++)
    {
        a=i;
    }
}


/* Main function. */
int main(void){

     u32 storedValues[100]={};
 int Status;
int j=0;
while(j<100){
 /* Execute the LED output. */
    storedValues[j] = LEDOutputExample();
    //printf("The J Value  %d \n \r", j );
   // printf("The STORED Values  %d \n \r", storedValues[j]);
    j++;
 }
int k;
printf("The ARRAY Values \n");
  for(k=0; k<100; k++)
  {

      printf("%d \n \r", storedValues[k]);
  }


 return 0;
}

Motor Forwards and Backwards

The following link shows how a circuit can be wired with a switch to make a motor move in two different directions

http://www.instructables.com/id/How-to-control-a-DC-motor-to-run-in-both-direction/

Tuesday, June 9, 2015

June 9 - Reading a signal using MAX11205







1) We should add a dc bias of 1.6V to a sine wave from a function generate and use an amplitude of 1.6 V (to stay below 3.3V). '

The maximum voltage that you use depends on the voltage of AVDD which is controlled by JP1.  When JP1 is in the position 1-2 (I think this is the default position), the maximum voltage is 2.85V, while in position 2-3, it is dictated by the Zedboard and is probably 3.3V.

Leave jumper JP1 in position 1-2 and limit the maximum voltage to 2.85V.  I always use an oscilloscope to confirm voltages befor I connect to equipment as the function generator controls are sometimes confusing.

2) Three pins are available.  They include V_in, Gnd, and Ref. '

V_in+ - Connect this to the output of the function generator.  The signal should be no more than 2.85V and no less than 0V.
V_in- - Connect this to the ground of the function generator.  It is also connected to the ground of the Zedboard though the Pmod connector.
Ref - This is an output from the board.  Leave Ref unconnected.



We made the following circuit that will allow us to offset the sine wave so that the wave will go from 0V to 2.8V.

schematic

However, we are reading in all zeros so we decided to start with just a constant voltage from the Zedboard. We connected ground from the pmod to ground on the max11205 peripheral and 3.3V from the pmod to the Vin on the peripheral. We used the following code:


 /* Input is on pin 3.  The program reads 8 bits of data sequentially and stores them as an 8 bit value.
The process of storage is shown using the LEDs.  Each bit is shifted to the left.  This is a program to
understand the bit-bang process and how the Maxim Integrated 11205 ADC works.*/

/* Include Files */
#include "xparameters.h"
#include "xgpio.h"
#include "xstatus.h"
#include "xil_printf.h"
#include "time.h"

/* Definitions */
#define GPIO_DEVICE_ID  XPAR_AXI_GPIO_0_DEVICE_ID /* GPIO device that LEDs are connected to */
#define LED 0xFC          /* Initial LED value - XX0000XX */
#define PMOD 0xFC         /* Initial LED value - XX0000XX */
#define LED_DELAY 100000000       /* Software delay length */
#define LED_CHANNEL 1        /* GPIO port for LEDs */
#define PMOD_CHANNEL 1        /* GPIO port for PMODs */
#define printf xil_printf       /* smaller, optimised printf */
#define PMOD_JA1_DEVICE_ID  XPAR_AXI_GPIO_1_DEVICE_ID
#define ABOUT_ONE_SECOND 74067512      //!< approx 1 second delay when used as argument with function delay(numberCyclesToDelay)
// Update this if uBlaze/Zynq CPU core frequency is changed, or if the external memory timing changes.
// Although emprirically tested to 1.0000003 seconds, it is not meant to be used for precise timing purposes

/* Definitions */
#define CLOCK_on 0x08    //high for the clock
#define DATAREADY_high 0x04   //high for data ready pin 3


XGpio Gpio, GpioP;           /* GPIO Device driver instance */



int LEDOutputExample(void)
{


 volatile int Delay;
 int Status;
 int led = LED; /* Hold current LED value. Initialise to LED definition */
 int pmod = PMOD;
 int WritetoLEDs;
 int i;
 u32 x;
 u8 uchPortWriteData=0;
 u8 uchPortReadData=0;
 u32 adcValue=0;
 int uchUseCalibrationMode;
 u32 storedValues[]={};
 int nClockCount;
 int j;

  /* GPIO driver initialisation */
  Status = XGpio_Initialize(&Gpio, GPIO_DEVICE_ID);
  if (Status != XST_SUCCESS) {
   return XST_FAILURE;
  }
  Status = XGpio_Initialize(&GpioP, PMOD_JA1_DEVICE_ID);
   if (Status != XST_SUCCESS) {
    return XST_FAILURE;
  }

  /*Set the direction for the LEDs to output. */
  XGpio_SetDataDirection(&Gpio, LED_CHANNEL, 0x00);


  /*Set the direction for the PMod - pin 3 is an input, rest are outputs. */
    XGpio_SetDataDirection(&GpioP, PMOD_CHANNEL, 0x04);

    WritetoLEDs =0x01;
    for(i =1;i<8;i++){
        XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, WritetoLEDs);
        delay(ABOUT_ONE_SECOND/3);
        WritetoLEDs=(int)(1<<i);
    }


  //  printf("Ready to receive.\n \r");
    delay(10);
    XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0xFF);

for(j=0;j<=50;j++)
{
    XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0x00);
 for(i=15;i>=0;i--)
    {
        // Send clock high
        uchPortWriteData |= CLOCK_on;
        XGpio_DiscreteWrite(&GpioP, 1, uchPortWriteData);

        delay(10);  // small delay, then read
        uchPortReadData = XGpio_DiscreteRead(&GpioP,1);
        delay(10);
        // Shift the GPIO read data to the lowest bit, mask off all the other bits, then shift i (15:0)
        // number of bits to set the appropriate bit in the
        if(((uchPortReadData >> 2) & 0x01)==0x01) // the serial bit is a one, set the bit
        {
            if(i==15)
                adcValue = 0xFFFF8000;  // extend the sign of the 2s complement number to bits 31..16, and set bit 15 = 1
            else
                adcValue |= (int)(1 << i);  // bit shift
        }
        uchPortWriteData &= ~CLOCK_on;// Clock in data via negative edge
        XGpio_DiscreteWrite(&GpioP, 1, uchPortWriteData);
        //XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, adcValue);


        // The 11205 device requires 25 clocks total to complete a read.
            // We have already sent (16) clocks, so send 9 more clocks.
            // (If self-calibration mode set then we send 10 more clocks.)
        uchUseCalibrationMode=0;
        if(uchUseCalibrationMode==1)
                nClockCount = 9;
            else
                nClockCount=8;
            for(i=nClockCount;i>=0;i--)
            {
                // Send clock high
                uchPortWriteData |= CLOCK_on;
                XGpio_DiscreteWrite(&GpioP, 1, uchPortWriteData);

                delay(10);  // small delay, then read
                uchPortWriteData &= ~CLOCK_on;// Clock in data via negative edge
                XGpio_DiscreteWrite(&GpioP, 1, uchPortWriteData);
                delay(10);
            }

    }


          printf("The ADC Value  %d \n \r", adcValue);
        storedValues[j]= adcValue;
        printf("The J Value  %d \n \r", j );
        printf("The STORED Values  %d \n \r", storedValues[j]);
        XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0x01);
        sleep(1);
        XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0x00);
        sleep(1);

}
  return XST_SUCCESS; /* Should be unreachable */
}



void delay(int nStopValue)
/**
* \brief       Loop for nStopValue iterations to provide a delay.
* \par         Details
*              It is commonly used with the constant 'ABOUT_ONE_SECOND' defined in maximPMOD.h for
*              setting approximate delays
*
* \param[in]   nStopValue    - number of iterations to loop
*
* \retval      None
*/
{
    int i=0;
    int a=0;

    for(i=0;i<nStopValue;i++)
    {
        a=i;
    }
}


/* Main function. */
int main(void){


 int Status;


 /* Execute the LED output. */
 Status = LEDOutputExample();
 if (Status != XST_SUCCESS) {
  xil_printf("GPIO output to the LEDs failed!\r\n");
 }


 return 0;
}



This is the output that we are getting and we are going to start debugging to understand why we are getting the weird values that we are getting and why it stops running after a certain amount of time.

Displaying image2.JPG

ADC Converter Objectves



A project using the Maxim Integrated 11205 ADC.

1. Connect a function generator output to one of the channels of an oscilloscope and produce a signal of 2V (1 volt peaks) at an arbitrary frequency.  Make sure you choose the sine wave as the signal type.

2. Connect the TTL/CMOS port of the function generator to the voltage and ground pins of the the Maxim Integrated 11205 ADC.

3. The output of the Converter will connect to the input of the zedboard on the pin we choose to make an input (pin 3 (JA3) matches up with the output pin of the ADC so that would be a good choice).

4.The output of the Zedboard (pin 4 - JA4) will connect to the input of the ADC chip (pin 4 called SCLK). SCLK stands for Serial Clock Input. Any externally created clock can be read through this port.


MAX11205PMB1 Board Photo
MAX11205 ADC:

Pin 3 : MISO: Data-ready output/serial-data output. This output serves a dual function. In addition to the serial-data output function, the MISO pin also indicates that the data is ready when it is pulled logic-low by the IC. Output data changes on the falling edge of SCLK.

Pin 4: SCK: 2-wire serial clock. The host must apply an external clock signal to shift data out from the IC.



What is bit-banging?

Bit-banging is a process used for serial communications; in our case from a peripheral module to a micro-controller (Zedboard). Reading the first value, a hi or lo state (a 1 or 0), on the input pin of the Zedboard gives us the value we want to store in the memory. The value on pin 3 is shifted two values down to pin 1 where it can be read and stored in the memory. This means that any other information sent over the 8 bits of the PMOD from the ADC will also be shifted.

The value, initially which will look something like 00000100 will be shifted down two bits to become 00000001. Of course if there were other hi states coming from the ADC that made the signal look like 00001111, the value would be shifted down two bits to become 00000011. The first 4 bits will always read 0 because the ADC converter only connects to the top 6 pins of the PMOD. Each PMOd has 12 pins (6 on top 6 on the bottom) that exchange serial information. The top two on the far left and the bottom two on the far left are simply power and ground ports. So each channel on the PMOD or the 8 pins leftover correspond to 8 bits of information that can communicate between the ZedBoard and the ADC.

As stated earlier, the ADC only sends 4 bit information in the top 4 bits of the Zedboard. So our "shifted value" will look something like 0001. But to keep things standard, I will write the value with the "empty" lo state first 4 pins (pins 5-8) and we get 00000001.

This value gets operated on by an AND operator with the value of 00000001 and if the values are the same, a 1 will be stored in the 16th bit of the registry. If they do not match up, a 0 will be placed in the 16th bit. After one clock cycle, (clock sent to ADC, ADC sends value to Zedboard, gets shifted down two bits, gets "AND operated", stored in the 16th bit) and the process starts again bit banging to the 15th bit and getting a new value from the ADC. The clock cycles 25 times until the 16-bit registry is filled up with some arbitrary value. Converting this number from binary will give us the value of some voltage being fed into the ADC.

The next step would be to save these values by allocating memory on the ZedBoard. I may have some code we can work with to do so.

Program was executed even though Zed Board was disconnected (Done by Frank Chietro and Ryan O'Keefe)