The objective of this guide is to:
- Power on the OBC
- Login to the OBC
- Create simulated telemetry
- Send telemetry to the COMMS
- Receive simulated telemetry
Power the OBC
Over the connectors or over the EPS subsystem.
Make sure it is running the last image of the OBC.
Login to the OBC
Login: root Password: root
Simulated telemetry generation
The next script is under /home/obc/scripts/01_sim_telemetry_gen.py
:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
This example will create a dummy packet with telemetry using CCSDS
"""
#%% Import libraries
import time
import can
from construct import BitStruct, BitsInteger, Padding, Struct, Float32l
from construct import Int16ul, Int8ul
#%% Define structures of CCSDS packet
# Define primary header of CCSDS
CCSDS_PRIM_HEADER = BitStruct(
"version" / BitsInteger(3),
"type" / BitsInteger(1),
"sec_header_flag" / BitsInteger(1),
"proc_id" / BitsInteger(11),
"seq_flags" / BitsInteger(2),
"seq_cnt" / BitsInteger(14),
"length" / BitsInteger(16)
)
# Define a dummy sensor data
SENSOR_DATA = Struct(
"temp" / Float32l,
"preassure" / Float32l,
"altitude" / Float32l,
"humidity" / Float32l
)
# Define our sample CCSDS packet
CCSDS_SAMPLE_PACKET = Struct(
"header" / CCSDS_PRIM_HEADER,
"data" / SENSOR_DATA
)
#%% Populate the packet with some data
ccsds_prim_header_dict = dict(
version = 0b1,
type = 0b0,
sec_header_flag = 0b0,
proc_id = 0b1,
seq_flags = 0b11,
seq_cnt = 0b0,
length = SENSOR_DATA.sizeof() + CCSDS_PRIM_HEADER.sizeof() - 1 # Length is calculated based on the lenght of the packet
)
sensor_data_dict = dict(
temp = 22.05,
preassure = 101.2,
altitude = 666,
humidity = 98.125
)
# Build the telemetry packet
sensor_data = SENSOR_DATA.build(sensor_data_dict)
ccsds_packet= CCSDS_SAMPLE_PACKET.build(dict(
header = ccsds_prim_header_dict,
data = sensor_data_dict
))
#%% Print the hex value of the packet
print("Sending CCSDS packet with the content: {}".format(ccsds_packet.hex()))
#%% We need to create a CFP packet in which we encapsule the CCSDS packet
# First define the CFP structures
CAN_CFP_ID = BitStruct(
Padding(3),
# Padding of 3 bits to be multiple of 8,
# discarted when adding to can message
"source" / BitsInteger(5),
"destination" / BitsInteger(5),
"type" / BitsInteger(1),
"remain" / BitsInteger(8),
"id" / BitsInteger(10)
)
#%%
# Create a function to send CFP packets
CAN_MAX_LENGTH = 8 # Max number of bytes in a message of CAN
CFP_BEGIN = 0b0
CFP_MORE = 0b1
# CFP Some variables
SOURCE = 0
DESTINATION = 1 # COMMS
ID = 63 # Sample id
# Define CAN bus
bustype = 'socketcan'
channel = 'can0'
bus = can.Bus(channel=channel, interface=bustype)
def send_CCSDS(ccsds_packet):
# Create a message and send it using CFP
num_packets = (len(ccsds_packet) - 1) // CAN_MAX_LENGTH + 1
remain = num_packets - 1
# Send the first frame
cfp_id_dict = dict(
source = SOURCE,
destination = DESTINATION,
type = CFP_BEGIN, # BEGIN
remain = remain,
id = ID # Sample identifier
)
cfp_id = CAN_CFP_ID.build(cfp_id_dict)
start = 0 # We start at 0
end = min(start + CAN_MAX_LENGTH, len(ccsds_packet))
print("Sending from {} to {}, remain {}".format(start, end, remain))
# Send first packet
msg = can.Message(arbitration_id=int.from_bytes(cfp_id, 'big'), data=ccsds_packet[start:end], is_extended_id=True)
bus.send(msg)
while(remain > 0):
remain -= 1 # We are sending a new one
# Send the first frame
cfp_id_dict = dict(
source = SOURCE,
destination = DESTINATION,
type = CFP_MORE, # BEGIN
remain = remain,
id = ID # Sample identifier
)
cfp_id = CAN_CFP_ID.build(cfp_id_dict)
start = end
end = min(start + CAN_MAX_LENGTH, len(ccsds_packet))
print("Sending from {} to {}, remain {}".format(start, end, remain))
# Send first packet
msg = can.Message(arbitration_id=int.from_bytes(cfp_id, 'big'), data=ccsds_packet[start:end], is_extended_id=True)
bus.send(msg)
bus.shutdown() # Close bus
#%%
# Send our packet over CAN with CFP
send_CCSDS(ccsds_packet)
After connecting the uCAN the output should be something like:
$ candump can0
can0 0008083F [8] 20 01 C0 00 00 15 66 66
can0 000C043F [8] B0 41 66 66 CA 42 00 80
can0 000C003F [6] 26 44 00 40 C4 42
Connect the COMMS
The destination of our CAN packet is the COMM subsystem, which its unique task is to relay all the incoming information over LoRa.
The steps are:
- Connect the comms
- Connect the Ground LoRa Receiver
The LoRa receiver act as a relay from LoRa to UART, so it can be received by the computer. Connect to the serial and the output should look something like this:
�ff�Aff�B�&D@�B::+1.*sc
We receive the information. But is in binary we are not able to understand it :/