Hi,

I just bought the APM 2.5 together with the Remzibi OSD (not the minimOSD).

Now I try to get the connection from the APM to the OSD with the adapter calbe for telemetry

http://store.diydrones.com/Adapter_cable_for_APM_2_5_p/kt-apm25-cab...

EDIT:  I want to send a big thank you to Heino R. Pull who send me a lot of informations and the very good working code for the ardurino mini to start the telemetry link and bring the APM 2.5 to send data to the remzibi OSD 3DR.

The original code can be downloaded here: http://www.heino.com/

Use this original Code to use the ardurino pro mini with an XBee.

If you don`t want to use the XBee, you need to do the wiring and code below.

(Tested with APM 2.5,  Arduplane 2.6 and Remzibi OSD 3DR)

Here is the modification from the osdmavlink.pde (I assume he will update it on his page soon, but maybe someone is interested)

<code>

// Mavlink to Remzibi OSD converter
// Using Ardustation code written by psmitty
// Heino Pull (heyno@heino.com) httpwww.heino.com
// Mavlink to Remzibi OSD compatible with ACM 2.7.3/2.8
#define MAVLINK10

#include <FastSerial.h>
#include <GCS_MAVLink.h>
#include <avr/pgmspace.h>
#include <LiquidCrystal.h>
#include <EEPROM.h>
#include <AP_EEPROMB.h>         // ArduPilot Mega RC Library
//#include <Time.h>


#include <Servo.h>
//AP_EEPROMB ee;
#undef PROGMEM
#define PROGMEM __attribute__(( section(".progmem.data") ))

#undef PSTR
#define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];}))

#define SERIAL_BAUD 57600
//#define BUZZERON // is the buzzer on?
FastSerialPort0(Serial);

// data streams active and rates
#define MAV_DATA_STREAM_POSITION_ACTIVE 1
#define MAV_DATA_STREAM_RAW_SENSORS_ACTIVE 1
#define MAV_DATA_STREAM_EXTENDED_STATUS_ACTIVE 1
#define MAV_DATA_STREAM_RAW_CONTROLLER_ACTIVE 1
#define MAV_DATA_STREAM_EXTRA1_ACTIVE 1

// update rate is times per second (hz)
#define MAV_DATA_STREAM_POSITION_RATE 1
#define MAV_DATA_STREAM_RAW_SENSORS_RATE 1
#define MAV_DATA_STREAM_EXTENDED_STATUS_RATE 1
#define MAV_DATA_STREAM_RAW_CONTROLLER_RATE 1
#define MAV_DATA_STREAM_EXTRA1_RATE 1
#define GET_PARAMS_TIMEOUT 200 //(20 seconds)
#define TOTAL_PARAMS 37
#define toRad(x) (x*PI)/180.0
#define toDeg(x) (x*180.0)/PI

float altitude=0;
float pitch=0;
float roll=0;
float yaw=0;
float longitude=0;
float latitude=0;
float velocity = 0;
unsigned long gpstime = 0;
int numSats=0;
int battery=0;
int currentSMode=0;
int currentNMode=0;
int droneType;
int autoPilot;
uint32_t custom_mode;
 int tdfix = 0;
int callsignprint = 0;
int waitingAck=0;
int paramsRecv=0;
int beat=0;

int find_param(const char* key)
{
  char buffer[15];
  for (int i=0; i<TOTAL_PARAMS; i++)
  {
//    get_Param_Key(buffer, i);
    if (strcmp(buffer,(const char*)key) == 0)
      return i;    
  }
  return -1;  
}

void gcs_update()
{
    // receive new packets
    mavlink_message_t msg;
    mavlink_status_t status;

    // process received bytes
    while(Serial.available())
    {
        uint8_t c = Serial.read();
        // Try to get a new message
        if(mavlink_parse_char(0, c, &msg, &status)) gcs_handleMessage(&msg);
    }
}

uint8_t received_sysid=0; ///< ID of heartbeat sender
uint8_t received_compid=0; // component id of heartbeat sender

void gcs_handleMessage(mavlink_message_t* msg)
{
  switch (msg->msgid) {
    case MAVLINK_MSG_ID_HEARTBEAT:
    {
      mavlink_heartbeat_t packet;
      mavlink_msg_heartbeat_decode(msg, &packet);
      custom_mode = packet.custom_mode;
      droneType = packet.type; // Don't pick up from the heartbeat now since there is some weirdness when the Planner is running
                               // and ArduPlane is running (get packet with type = 1 and type =0 also - confused this logic)
                                  
      autoPilot = packet.autopilot;

      beat = 1;
      break;
    }

    case MAVLINK_MSG_ID_ATTITUDE:
    {
      // decode
      mavlink_attitude_t packet;
      mavlink_msg_attitude_decode(msg, &packet);
      pitch = toDeg(packet.pitch);
      yaw = toDeg(packet.yaw);
      roll = toDeg(packet.roll);
      break;
    }

  #ifdef MAVLINK10
      case MAVLINK_MSG_ID_GPS_RAW_INT:
          #else // MAVLINK10
 
      case MAVLINK_MSG_ID_GPS_RAW:
          #endif // MAVLINK10
          
              {
                // decode
          
          #ifdef MAVLINK10
                mavlink_gps_raw_int_t packet;
                mavlink_msg_gps_raw_int_decode(msg, &packet);
                velocity = packet.vel/100.0;
                latitude = packet.lat/1e7;
                longitude = packet.lon/1e7;
                altitude = packet.alt/1000.0;
                gpstime = packet.time_usec>>16;
          #else // MAVLINK10
                mavlink_gps_raw_t packet;
                mavlink_msg_gps_raw_decode(msg, &packet);
                velocity = packet.v;
                latitude = packet.lat;
                longitude = packet.lon;
                altitude = packet.alt;  
                gpstime = packet.usec >> 16;
          
          #endif // MAVLINK10
                tdfix = packet.fix_type;
                      numSats = packet.satellites_visible;
                create_Remzibi_output();
    
      break;
    }

    case MAVLINK_MSG_ID_GPS_STATUS:
    {
      mavlink_gps_status_t packet;
      mavlink_msg_gps_status_decode(msg, &packet);        
//      numSats = packet.satellites_visible;
//      Serial.print(numSats);
      break;
    }
    case MAVLINK_MSG_ID_RAW_PRESSURE:
    {
      // decode
      mavlink_raw_pressure_t packet;
      mavlink_msg_raw_pressure_decode(msg, &packet);
      break;
    }
     case MAVLINK_MSG_ID_SYS_STATUS:
    {

        mavlink_sys_status_t packet;
        mavlink_msg_sys_status_decode(msg, &packet);
    #ifdef MAVLINK10
        battery=packet.voltage_battery;  
    #else // MAVLINK10
      currentSMode = packet.mode;
      currentNMode = packet.nav_mode;
      battery = packet.vbat;
    #endif // MAVLINK10
      break;
    }
    case MAVLINK_MSG_ID_PARAM_VALUE:
    {
      // decode
      mavlink_param_value_t packet;
      mavlink_msg_param_value_decode(msg, &packet);
      const char * key = (const char*) packet.param_id;
      break;
    }
  }
}

void send_message(mavlink_message_t* msg)
{
  uint8_t buf[MAVLINK_MAX_PACKET_LEN];
  uint16_t len = mavlink_msg_to_send_buffer(buf, msg);

  for(uint16_t i = 0; i < len; i++)
  {
    Serial.write(buf[i]);
  }
}

void start_feeds()
{
  mavlink_message_t msg;
  mavlink_msg_request_data_stream_pack(127, 0, &msg, received_sysid, received_compid, MAV_DATA_STREAM_RAW_SENSORS, MAV_DATA_STREAM_RAW_SENSORS_RATE, MAV_DATA_STREAM_RAW_SENSORS_ACTIVE);
  send_message(&msg);
  delay(10);
  // mavlink_message_t msg3;
  mavlink_msg_request_data_stream_pack(127, 0, &msg, received_sysid, received_compid, MAV_DATA_STREAM_EXTENDED_STATUS, MAV_DATA_STREAM_EXTENDED_STATUS_RATE, MAV_DATA_STREAM_EXTENDED_STATUS_ACTIVE);
  send_message(&msg);
  delay(10);
  // mavlink_message_t msg4;
  mavlink_msg_request_data_stream_pack(127, 0, &msg, received_sysid, received_compid, MAV_DATA_STREAM_RAW_CONTROLLER, MAV_DATA_STREAM_RAW_CONTROLLER_RATE, MAV_DATA_STREAM_RAW_CONTROLLER_ACTIVE);
  send_message(&msg);
  delay(10);
  // mavlink_message_t msg1;
  mavlink_msg_request_data_stream_pack(127, 0, &msg, received_sysid, received_compid, MAV_DATA_STREAM_POSITION, MAV_DATA_STREAM_POSITION_RATE, MAV_DATA_STREAM_POSITION_ACTIVE);
  send_message(&msg);
  delay(10);
  // mavlink_message_t msg5;
  mavlink_msg_request_data_stream_pack(127, 0, &msg, received_sysid, received_compid, MAV_DATA_STREAM_EXTRA1, MAV_DATA_STREAM_EXTRA1_RATE, MAV_DATA_STREAM_EXTRA1_ACTIVE);
  send_message(&msg);
  delay(460);
}

void setup()
{
  Serial.begin(SERIAL_BAUD);
  delay(300);
}

int start_count = 0;

void loop()
{

  gcs_update();
 
  if ((start_count< 3) && (millis() >(3000+(start_count * 2000)))) //send start feed after 3 seconds of powerup - need time for heartbeat to be received - try 3 times with 2 seconds between each try
  {
    start_feeds();
    start_count++;
  }
}

void pids() // menu 2
{
}

void create_Remzibi_output()
{
//      Distance_Home=calc_dist(Latitude_Home, Longitud_Home, latitude, longitude);
//    Bearing_Home=calc_bearing(Latitude_Home, Longitud_Home, latitude, longitude);
//    SvBearingHome=Bearing_Home;
//    Angle_Home=ToDeg(atan((float)(altitude-Altitude_Home)/(float)Distance_Home));
//    Bearing_Home = 180-(Bearing_Home/2.0);
//    
//    // Offset for servo limit
//    Bearing_Home = Bearing_Home + offset;
//    if (Bearing_Home > 180.0)
//       Bearing_Home = Bearing_Home - 180.0;
//    else
//    {
//        if (Bearing_Home <0.0)
//           Bearing_Home = Bearing_Home + 180.0;
//    }

    print_GPGGA();
     delay(30);
    print_GPRMC();
     delay(30);
    print_sonar();
     delay(20);
     callsignprint++;
     if (callsignprint>100) {
      
       print_remzibi_mode();
       delay(20);
       callsignprint=0;
     }
}


int availableMemory() {
  int size = 2048;
  byte *buf;

  while ((buf = (byte *) malloc(--size)) == NULL)
    ;

  free(buf);
  return size;
}

</code>

Tags: 2.5, APM, OSD, Remzibi, port, telemetry

Views: 5846

Attachments:

Reply to This

Replies to This Discussion

I did see you mentioned a 1.753DR software - I'll look at this to see - but it sounds like the right version for it to work.  The configuration bin file is only to configure the display to place the various data values in the right spot.  You can tailor this as you see fit, but one user did want to see what I used on my quad.

Also - if you'll never use a GCS with the APM, I can give you code to have the firmware send a start MAVLINK feed command - but you'll have to wire the Pro Mini's xmit back to the APM.

I took a look at the 3DR Remzibi setup document and it seems that the default baud rate when using the Mediatek GPS is 38400 baud instead of 57600 which I use by default in my Arduino Pro mini firmware.  Since I don't have the 3DR Remzibi, I'm not sure what the startup OSD screen looks like.  The firmware is based on Remzibi 1.75 and the Remzibi version allows an autodetection of baud rate at startup.  Does the 3DR Remzibi firmware do the same thing or does it skip this step and assume 38400 (which is the default for the Mediatek)?

If it assumes 38400, then it will be necessary to change the APM code to output Mavlink at 38400 instead of 57600 and my firmware should work ok.  This will require recompiled ACM 2.7.3 or ACM 2.8 for the different baud rate. 

Please let me know if your OSD tries different baud rates or not.  If not, I can advise further on modifying ACM 2.8 to change the baud rate for Mavlink output.

Heino

I don`t use the Mediatek GPS anymore but the 3DR GPS uBlox LEA-6 with the APM.

The remzibi 3dr is also using the 1.75 firmware, but slightly changed to support the second button and LED`s. I assume there are not major differences.

The startup screen is also scanning the GPS baudrate. The numbers are changing during the startup (I assume that`s the baud rate).

I think I understand the issue now. I don`t have a 3DR radio attached to the APM and the mavlink doesn`t start up because of this. I just tried to attach the OSD to the APMs telemetry link. Hopefully I get it running without an xbee and can manipulate the APM to send mavlink data anyway.


/Stefan

I`m back with some more information.

It seems that I don`t get any feedback from the APM.

void gcs_update()
{
    mavlink_message_t msg;
    mavlink_status_t status;
    while(Serial.available())
    {
        uint8_t c = Serial.read();
        // Try to get a new message
        if(mavlink_parse_char(0, c, &msg, &status)){
          gcs_handleMessage(&msg);        // Here we don`t get any messages because if statement is false.
        }
    }
}

I`ve set the baudrate to 57 which is correct and it even can detect the serial connection to the apm (while serial.available is true)

As far as I understand well, the XBEE is establishing e mavlink connection to the apm and the ardurino pro mini is just listening the traffic. How can I get it running without the XBEE? Is there a function to establish the mavlink connection which we can use on the pro mini?

Here is the code to start the Mavlink feeds - this is from the Ardustation 2 code and it should start it up. 

Add this in osdmavlink just before the void setup() and after the code sends the "hello" it should then send on the serial port the code to start mavlink.  I haven't tried this since I have to rewire my Remzibi install, but I will try this later today when I have some time.

uint8_t received_sysid=0; ///< ID of heartbeat sender
uint8_t received_compid=0; // component id of heartbeat sender

void send_message(mavlink_message_t* msg)
{
uint8_t buf[MAVLINK_MAX_PACKET_LEN];

// Serial.write(MAVLINK_STX);
// Serial.write(msg->len);
// Serial.write(msg->seq);
// Serial.write(msg->sysid);
// Serial.write(msg->compid);
// Serial.write(msg->msgid);
uint16_t len = mavlink_msg_to_send_buffer(buf, msg);
for(uint16_t i = 0; i < len; i++)
{
Serial.write(buf[i]);
}
// Serial.write(msg->ck_a);
// Serial.write(msg->ck_b);
}
void start_feeds()
{

mavlink_message_t msg;
mavlink_msg_request_data_stream_pack(127, 0, &msg, received_sysid, received_compid, MAV_DATA_STREAM_RAW_SENSORS, MAV_DATA_STREAM_RAW_SENSORS_RATE, MAV_DATA_STREAM_RAW_SENSORS_ACTIVE);
send_message(&msg);
delay(10);
// mavlink_message_t msg3;
mavlink_msg_request_data_stream_pack(127, 0, &msg, received_sysid, received_compid, MAV_DATA_STREAM_EXTENDED_STATUS, MAV_DATA_STREAM_EXTENDED_STATUS_RATE, MAV_DATA_STREAM_EXTENDED_STATUS_ACTIVE);
send_message(&msg);
delay(10);
// mavlink_message_t msg4;
mavlink_msg_request_data_stream_pack(127, 0, &msg, received_sysid, received_compid, MAV_DATA_STREAM_RAW_CONTROLLER, MAV_DATA_STREAM_RAW_CONTROLLER_RATE, MAV_DATA_STREAM_RAW_CONTROLLER_ACTIVE);
send_message(&msg);
delay(10);
// mavlink_message_t msg1;
mavlink_msg_request_data_stream_pack(127, 0, &msg, received_sysid, received_compid, MAV_DATA_STREAM_POSITION, MAV_DATA_STREAM_POSITION_RATE, MAV_DATA_STREAM_POSITION_ACTIVE);
send_message(&msg);
delay(10);
// mavlink_message_t msg5;
mavlink_msg_request_data_stream_pack(127, 0, &msg, received_sysid, received_compid, MAV_DATA_STREAM_EXTRA1, MAV_DATA_STREAM_EXTRA1_RATE, MAV_DATA_STREAM_EXTRA1_ACTIVE);
send_message(&msg);
delay(460);

}


void setup()
{
Serial.begin(SERIAL_BAUD);
Serial.println("hello");
Serial.println(availableMemory());
delay(300);
start_feeds();

}

Hi Heino,

thanks a lot for your help. I spent hours today to find a way to do this without compilation errors :)

I get a binary output message now on the serial monitor but it`s just one and It still won`t to get any messages from the APM.

The if statement is still false.

if(mavlink_parse_char(0, c, &msg, &status))

I`ll try to find out a bit more to give more details on it.

/Stefan

It sounds like you're closer. I will try a little later the same thing
to make sure the command is working ok and I have a logic analyzer
here to see what comes back from the APM.  What version of ACM code
are you using so I can check?

Be careful of the if statement above - it will be false while a full message is being processed - it will suddenly become true after all the bytes are valid in the buffer. If it never goes true after a second or so there is a problem.

I just added a Serial.println if the statement becomes true. Thats my way of debugging foreign code to find out the point where it hangs and I never get the print on the serial monitor. What do you mean with ACM code? The FW of the apm is Arduplane 2.65

If you mean your code... Then I`m working on osdmavlinkACM2_7_3.

(I really feel like a kid in the jungle, sorry if I have such stupid questions)

Actually that was helpful - I've been testing with Arducopter 2.7.3 and 2.8.  I haven't tried lately with Arduplane.  In my test I'll do later - I'll give Arduplane 2.65 a try.

Be careful with the println statements as they are also then transmitted back to the APM as you're watching it on the serial monitor. I'll try the same technique with my experiment to make sure that the Mavlink parse isn't disrupted by having println statements at the wrong spot after having started the feed. 

OK, I`ll remove all serial prints, but I also tested without all the prints with the same result.

I just confirmed on the bench that the code I sent you is not working here.  I have to modify it a bit and I should have a solution for you in a few hours.

RSS

Groups

Season Two of the Trust Time Trial (T3) Contest 
A list of all T3 contests is here. The current round, the Drone Delivery Challenge, is here

© 2014   Created by Chris Anderson.   Powered by

Badges  |  Report an Issue  |  Terms of Service