Jump to content
  • 0

GPS Pmod


HelplessGuy

Question

Hello everyone,

I bought for my Zedboard the GPS Pmod.

I wrote something about reading the datas out with UART.

Do you have some example code, how to do this? And is it possible to connect the GPS Module directly to my Pmod connections? And do I take the AXI GPIO block in the block diagram to solve this?

 

Edit:

I was able to solve it. But I do not really know now why. I think that I did some mistakes with the interrupt handling. I use now polled mode and now it is working perfectly. But I am still interested in the hardware design. I want to understand how the interrupt is working

Link to comment
Share on other sites

Recommended Posts

Thank you so much!   I am using an an Arty S7.   I have a file with the constraints that is specific for the board and have been getting my specific constraints from that.  I've attached my constraints and screenshots of my block diagram and the HDF summary.  Note that the first example we did, which sent simple text from the UART worked fine.    The failure came, as I mentioned, when I tried to run CfgInitialize. Interestingly it was able to call Initalize and Start.   I downloaded the project so I can see if I can get it to run.   My guess is I'll need to modify the constraints, etc.   Thank you again!!

blockdesign2019-07-24 19-20-31.png

hdf-file-2019-07-24 19-25-14.png

UART_IO_const.xdc

Link to comment
Share on other sites

Hi @HelplessGuy,

Please try making a project with only the Pmod GPS and Zynq processor. Then add the UART and GPIO IP cores after you have got the Pmod GPS going correctly. Also you have changed the Zynq processor. For your initial project with just using the Pmod GPS only add the interrupts to the  ZYNQ processor and leave everything else with the default settings.  Please use the Digilent board files which not only works with the Digilent IP Cores like the Pmod GPS IP Core but also becomes the default setting for the ZYNQ processor when running block automation. 

thank you,

Jon

Link to comment
Share on other sites

Hi @cepwin,

Welcome to the Digilent Forums!

To better assist you I would like a little more information about your project. From the linker script I can see that you are using Vivado 2019.1 and Microblaze  and not ZYNQ.  

1. What FPGA development board are you using? 

     a. If a Digilent FPGA are you using the Digilent board files?

2. Please attach a screen shot of your block design. 

Here is a verified Pmod GPS Microblaze project using Vivado 2019.1 and the Arty-A7-35T(Artix-7). I have also attached screens shots of the Block design, SDK, the block automation for microblaze and the tera term serial output.

best regards,

Jon

image.png

image.png

image.png

image.png

Link to comment
Share on other sites

Thanks!  I will have to try downloading  over the weekend!

I tried generating the bit stream and also tried letting it upgrade the software...I was never able to get it  to work.  I even tried generating a new project using other examples.

Link to comment
Share on other sites

@cepwin,

There's a real easy way to debug whether or not you are getting a fix or not.  Remove the FPGA design, and replace it with a pass through from the GPS UART transmit pin to the FT2232 UART RX transmit pin.  You can then use your favorite terminal program, mine is minicom some like teraterm, to examine the NEMA stream produced by the GPS device.  It's typically 9600 Baud, 8 data bits, no parity and one stop bit.  It's also pseudo-human readable--line upon line of CSVs--you should then be able to tell if you are getting lock or not.

I see no reason why you wouldn't be getting lock from your upstairs bedroom.

Also, for your security, you probably don't want to paste the NEMA stream coming out of the device here for discussion--since it may well reveal the coordinates of your bedroom.

Dan

Link to comment
Share on other sites

That you Dan!   I did a little googling over lunch and realized there's a very simple/stupid reason I'm not getting a signal....I don't have the GPS module....I see Digilent sells one a long with some other sensors/etc. that work with the Arty s7.   Those could be fun to play with.   I did create a full Microblaze with memory and UART and that appears to be good.   I just have to fix the code to use the UART library for that rather than the simple Microblaze that my class example used.   What I realized is Vivado will generate the necessary headers based on your design,

I also want to thank Jon again for his help as well.    I have learned so much working this issue.

Link to comment
Share on other sites

Hi @cepwin,

Have you added the Vivado library to your Vivado 2019.1 installation? You can do this from inside Vivado by Choosing settings in the Project Manager in the upper left, expand the IP selection in Project Settings and choose Repository. You can then add in the path to the Vivado-Library from Digilent (which you can download from our GitHub here). This should let you generate the bitstream.

Otherwise, you don't need to open up Vivado at all. If you have a fresh project you can open Xilinx SDK 2019.1, choose the workspace folder when it prompts you as the sdk folder source (as an example, mine is C:\Users\jcolvin\Documents\VivadoPrj\Arty-S7-PmodGPS_Vivado_2019_1\Arty-S7-PmodGPS_Vivado_2019_1.sdk) and wait for SDK to finish loading the workspace. When it is completed, you should see the hardware platform_0, the PmodGPS application folder, and the PmodGPS_bsp. You can then click the Xilinx tab at the top of the GUI, and choose to program the FPGA with the bitstream it finds. You will then want to connect to your board with your serial terminal of choice (I used TeraTerm) otherwise you won't see anything printing out. I then right-click on the PmodGPS application folder and choose Run As->Launch on Hardware (System Debugger). I then see the data printing out on the serial terminal.

Is this what you did for your project?

Thanks,
JColvin

Link to comment
Share on other sites

Hi @HelplessGuy,

Here is the complete Vivado 2018.2 Nexys 4DDR with Pmod GPS project I used.  I currently do not have the bandwidth to make the same project for the Zedboard. I would suggest to open this project and look at how I connected the Pmod GPS.

1) For the Zedboard all you would need to do is add the zynq processor(make sure to use the digilent board files when creating the project). Then at the vivado library to the ip repository. Then add the Pmod GPS to one of the ports I.E. JA,Jb,JC.

2) Next run block automation on the zynq processor and add interrupts to it. Then connect the interrupt to the interrupt on the Pmod GPS. Next validate the block design create a wrapper and generate the bitstream.

3) Then export hardware including the bitstream and launch SDK.

4) Once in SDK create an empty application. Add the main.c to the scr file in the application.  Program FPGA and rich click on the application and run as->launch on hardware(system debugger). 

cheers,

Jon

Link to comment
Share on other sites

Hi @HelplessGuy,

this piece of code demonstrate how to perform UART I/O communications with your board. It test the switches , buttons , and LEDs status using Teraterm.

/* Engineer : Jordan Christman @ Udemy
 *
 *
 * This file is a generated sample test application.
 *
 * This application is intended to test and/or illustrate some
 * functionality of your system.  The contents of this file may
 * vary depending on the IP in your system and may use existing
 * IP driver functions.  These drivers will be generated in your
 * SDK application project when you run the "Generate Libraries" menu item.
 *
 */

#include <stdio.h>
#include <string.h>
#include "xparameters.h"
#include "xil_cache.h"
#include "xiomodule.h"

int main()
{
   int done = 0;
   int byte_count = 0;
   int execute_cmd;
   char command[6];
   char led_cmd[3];
   char led_num[2];
   u8 tmp_rx_buf;
   u8 rx_buf[40];
   u32 button_data = 0;
   u32 switch_data = 0;
   u32 led_data = 0;
   u32 data;
   XIOModule iomodule;

   Xil_ICacheEnable();
   Xil_DCacheEnable();

   // Initialize module
   data = XIOModule_Initialize(&iomodule, XPAR_IOMODULE_0_DEVICE_ID);
   data = XIOModule_Start(&iomodule);
   data = XIOModule_CfgInitialize(&iomodule, NULL, 1);
   xil_printf("CFInitialize returned (0 = success) %d\n\r", data);

   print("---Enter a command---\n\r");

   // While loop until user enters "finish" command
   while(done == 0)
   {
	   execute_cmd = 0;
	   memset(rx_buf, 0, sizeof(rx_buf));
	   byte_count = 0;

	   // Build up message from UART Terminal
	   while (execute_cmd == 0)
	   {
		   // Read UART data
		   while ((data = XIOModule_Recv(&iomodule, &tmp_rx_buf, 1)) == 0);

		   rx_buf[byte_count] = tmp_rx_buf;

		   if (rx_buf[byte_count] == '\n')
			   execute_cmd = 1;

		   byte_count++;
	   }

	   // Build the command arrays
	   memcpy(command, &rx_buf[0], 6);
	   memcpy(led_cmd, &rx_buf[0], 3);
	   memcpy(led_num, &rx_buf[4], 2);

	   // Read the button & switch status
	   button_data = XIOModule_DiscreteRead(&iomodule, 1);
	   switch_data = XIOModule_DiscreteRead(&iomodule, 2);

	   // Execute the received command
	   if (strcmp(led_cmd, "led") == 0)
	   {
		   led_data = led_num[1] - 48;

		   if ((led_num[0] - 48) == 1)
			   led_data += 10;

		   XIOModule_DiscreteWrite(&iomodule, 1, led_data);
	   }
	   else if (strcmp(command, "button") == 0)
		   xil_printf("Button Status: %d\n\r", button_data);
	   else if (strcmp(command, "switch") == 0)
		   xil_printf("Switch Status: %d\n\r", switch_data);
	   else if (strcmp(command, "finish") == 0)
		   done = 1;
	   else
		   print("Command is invalid, re-enter below:\n\r");

// Debugging print outs below
//	   print("Command: ");
//	   print(command);
//	   print("\n\r");
//
//	   print("LED_cmd: ");
//	   print(led_cmd);
//	   print("\n\r");
//
//	   print("LED_num: ");
//	   print(led_num);
//	   print("\n\r");

   }

   print("---Exiting main---\n\r");
   Xil_DCacheDisable();
   Xil_ICacheDisable();
   return 0;
}

hope will benefit from it.

Link to comment
Share on other sites

I must say I share D@n's opinion here.

What I would do is

  • start with a plain serial port. Create a dumb (non-clocked) FPGA design that routes the FTDI chip's UART pins to some GPIOs, and hook up the GPS module. Alternatively, use a standalone FTDI-to-UART module or equivalent.
  • Fire up teraterm (e.g.) on the PC, open the COM port, set the correct baud rate.
  • Check that the GPS module responds as expected.
  • Check that the message format is exactly as you expect it.

I suspect this assumption

>> it seems, that the given functions from digilents pmodgps.h heather are doing already the right stuff

won't hold.

What you're trying reminds me of the old joke about a gynecologist retraining as a car mechanic?

Link to comment
Share on other sites

@HelplessGuy,

The fundamental discipline of all engineering is to be able to take a problem, such as the GPS not working for you, and to break it down into pieces in order to figure out which piece is broken.  This was my advice to you above.

I'm a little confused by your response saying that you don't need to do this.  Does that mean that things are finally working for you?

Dan

Link to comment
Share on other sites

@HelplessGuy,

This point is actually going in the wrong direction and taking you away from finding whatever bug you are struggling with.  Your first question should be whether or not you are receiving valid GPS data, and only secondly whether or not that data is processed properly.

GPS data is provided via a stream of text from the PMod GPS's UART port.  It's pseudo-human legible.  At this point, you need to first demonstrate that you are able to  receive the stream of text.  Only after that does it make sense to talk about whether the text can be decoded properly.  This sends us back to the issue with the character pointers that we were discussing above.

Have you tried a simple design that just connects the serial output port to a serial input port of your zedboard?  (I assume it has one in MDIO somewhere, although I haven't used the Zedboard enough to know.)  You would then need to process, by hand, enough of the NMEA messages to know that a signal exists, that it has been properly received, and that the GPS receiver had actually gotten a fix.  IMHO, this is the step you are missing.

Dan

Link to comment
Share on other sites

Hi @D@n  @jpeyron 

thanks for this. But I do not think, that the pointers are the problem at the moment. I think, that there is a mistake in the function.

double test;
test = GPS_GetTime(&GPSInst);

printf("%f\n", test);

I tested it also with this. And I also get the value 0.000 back. So we should forget the pointers at the moment and focus, why this function is not delivering any correct value.

Link to comment
Share on other sites

@HelplessGuy,

It looks like you are struggling with a basic misunderstanding of how C works.  You might wish to check some blogs or tutorials to learn a bit more about C pointers.  In particular, if you declare ptr_gps as a character, then it will only ever represent one character--not what you want.  A string in C is represented by a character array.  For this you *need* a pointer.  Declaring it as anything else won't work.

The misunderstanding seems to come in from the fact that your print statement needs to pass the pointer, not the character value referenced by the pointer.  To do this you want to pass ptr_gps without the star in front of it.  Keep your declaration the same.

Since this is a confusion about how C works, let's build an example that you can try on your desktop first.  Once you understand this working on your desktop, then you'll have the confidence to proceed to MicroBlaze again.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
  
char *get_string(char *ptr) {
	strcpy(ptr, "This is a string\n");
	return ptr;
}

char	*sptr;

int main(int argv, char **argv) {
  // Allocate a space to hold our string
  sptr = malloc(128);
  
  // Get a copy of our string
  sptr = get_string(sptr);
  
  // Print the string out.  Note the lack of the *
  printf("My string is: %s\n", sptr);
  
  // Free the space we allocated for our string in the first place
  free(sptr);
  
  // And exit with success
  return EXIT_SUCCESS;
}

I've just scribbled this together.  I haven't tested this, so it may or may not have bugs within it.

You might want to take particular note of what lines contain the "*" and which lines don't.  It's important.  In particular, the variable declarations for the pointers use the *, but nowhere else.  Were this code to reference a value found within the string, we might've referenced either *sptr or sptr[0], but that's not what you were trying to do above and so I haven't done that here.  Further, to print the whole string, you need to keep the "*" out of the printf.  Had you wanted to print one character only, that would have a different syntax.

A good C/C++ tutorial should also explain this in case I'm confusing you.

Dan

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...