Heading information as data stream

Hello!

Is there a possibility to ouput the current heading via a datastream? I managed to setup a serial port to get the NMEA string. (Serial Port Configuration Options — Copter documentation)

I noticed there is a heading segment in the string, however it seems to be incorrect and does not update when the drone is being moved.

$GPHDG,34.1,0,E,0,E*68

Does someone know the easiest solution to get the heading information on a e.g. 1Hz basis?

Thanks!!

Does anybody know a solution?

my understanding is that it only supports gps output.

You could use an arduino to convert mavlink data to the nmea values you want as the mavlink telemetry stream will have all the data you need.

1 Like

You can write a small LUA script to get ahrs heading and GPS pos, format it and send to a serial port…

1 Like

I started doing that, but I am far from a dev.
Managed to get a string containing all data I need and send it to Mission Planner:

pos = ahrs:get_position()
hdg = math.deg(ahrs:get_yaw())
gcs:send_text(6, string.format(“Lat:%f,Lon:%f,Hdg:%.0f”, pos:lat(), pos:lng(), hdg))

But I don’t understand how I can send this string via UART.
There is an example here but this is just a riddle to me:

What is “step”?
Where is the actual data contained?

Any help is much appreciated!

You are almost there…
You need to set SERIALx_PROTOCOL to 28 (scripting).

Then

local port = serial:find_serial(0)
port:begin(115200)
port:set_flow_control(0)

function update()

  -- get data, where data is the string you assembled.
  port:write(data)
  return update, 100  -- 100 is 100ms, adjust it to the needed refresh data
end

return update()
1 Like

Thank you…

Unfortunately I can’t get this to work.
I have a port open (at least it is not throwing any errors) but no data is being sent.
I tried port:write(5), which means “5” should be sent, right?

local baud_rate = 9600
local port = assert(serial:find_serial(0),“Script unable to find scripting serial port”)
port:begin(baud_rate)
port:set_flow_control(0)

function update()

port:write(5)
return update, 1000

end

return update()

The port is working, tested it with the build in NMEA String when the port is set to 20.
Also, since I can supposedly only send numbers, is data = string.byte(string) the correct way?

Thanks again…!

Not sure I follow :slight_smile:

How can I send for example the number “3”?

Sorry my bad… yes the port:write(5) writes the byte 5
To send a string you have to iterate somehow like this

if str ~= nil then
    for idx = 1, #str do
        port: write(str:byte(idx))
    end
end

Thanks! The string length is 41, and the for loop is working, however there is still no data being received.

Tried different, redundant? syntax just to get anything…

if str ~= nil then

	for idx = 1, #str, 1 do
		port:write(str:byte(idx))
		port:write(string.byte(str,idx))
		--gcs:send_text(6, idx)
	end

else

gcs:send_text(6, "Script string nil")

end

I think there is also some decoding needed, similar as mentioned here https://github.com/ArduPilot/ardupilot/blob/master/libraries/AP_Scripting/examples/UART_log.lua

I have a feeling that it must be replaced by a simple local port=serial:find_serial(0)

Sorry, took me some time to test it.

Unfortunately it isn’t working with local port=serial:find_serial(0) neither.

I checked again, the port is working with the build in NMEA String when the port is set to 20, just not with the script.

My code atm:

local FREQUENCY = 2000
local baud_rate = 9600

local port = assert(serial:find_serial(0),"Script unable to find serial port")
--local port=serial:find_serial(0)
port:begin(baud_rate)
port:set_flow_control(0)

function update()

	if not ahrs:healthy() then
		gcs:send_text(6, "Script waiting for AHRS initialization")
		return update, FREQUENCY
	end

	hdg = math.deg(ahrs:get_yaw())

	if hdg <0  then
		hdg = hdg+360
	end

    pos = ahrs:get_position()

	--gcs:send_text(6, string.format("Lat:%f,Lon:%f,Hdg:%.0f", pos:lat(), pos:lng(), hdg))

	--str = string.format("Lat:%f,Lon:%f,Hdg:%.0f", pos:lat(), pos:lng(), hdg)
	str = string.format("%f%f%.0f", pos:lat(), pos:lng(), hdg)

	gcs:send_text(6, "Script string: " .. str)
	gcs:send_text(6, "Script string length: " .. #str)

	if str ~= nil then

		for idx = 1, #str, 1 do
			port:write(str:byte(idx))
			port:write(string.byte(str,idx))   --redundant?
			gcs:send_text(6, str:byte(idx))
		end

	else

	gcs:send_text(6, "Script string nil")

	end

  return update, FREQUENCY

end

return update()

OK, gimme some time. I put together a test rig.

1 Like

Not that easy after all…?

Well, sorry I was drawn into another project and forgot it.
But here are my findings.
I put a FTDI USB/Serial converter to Telemetry port1 on a Orange Cube and connected it to my PC and open the port in a Serial terminal. (speed set to 9600)
Serial1_protocol was set to 28, speed to 9600
Since I tested it inside, I commented out the ahrs ready waiting and entered a false coordinates. (See correct script below).
And it was working just fine, I got the cords and heading in the serial terminal window. (I used SerialTool) So it has to be something with your setup…

local FREQUENCY = 2000
local baud_rate = 9600

local port = assert(serial:find_serial(0),"Script unable to find serial port")
local port=serial:find_serial(0)
port:begin(baud_rate)
port:set_flow_control(0)

function update()

	-- if not ahrs:healthy() then
		-- gcs:send_text(6, "Script waiting for AHRS initialization")
		-- return update, FREQUENCY
	-- end

	hdg = math.deg(ahrs:get_yaw())

	if hdg <0  then
		hdg = hdg+360
	end

    -- pos = ahrs:get_position()

	--gcs:send_text(6, string.format("Lat:%f,Lon:%f,Hdg:%.0f", pos:lat(), pos:lng(), hdg))

	--str = string.format("Lat:%f,Lon:%f,Hdg:%.0f", pos:lat(), pos:lng(), hdg)
	-- str = string.format("%f%f%.0f", pos:lat(), pos:lng(), hdg)
   str = string.format("14.66526 35.7762 %.0f",  hdg)

	gcs:send_text(6, "Script string: " .. str)
	gcs:send_text(6, "Script string length: " .. #str)

	if str ~= nil then

		for idx = 1, #str, 1 do
			port:write(str:byte(idx))
		end

	else

	gcs:send_text(6, "Script string nil")

	end

  return update, FREQUENCY

end

return update()

2 Likes

Thank you for taking the time! I will test it!

Are you using the pro version of Serial Tool?
I am unsure about the settings there to just receive data… D:

This is my not existing knowledge about serial connections coming back to me…
What is the correct settings in Serial Tool to receive data?
Do both RX and TX ports need to be open? When I try to open the port in serial tool, the one on the drone cannot be opened and vice versa, because only one can be open…?

I used Device Monitoring Studio to just sniff the incoming data for the NMEA String.

I figured it out.
I used Serial 3 (GPS1) on the Pixhawk 2.1 carrier board. (TX and GND pins)
When I switched to Serial 4 (GPS 2) it worked immediately.
We had a similar issue recently - we just switched the ports and it worked.
Thank you regardless for all the support!

1 Like