IR Communication between Arduino and Kilobots

I want my Arduino Nano Atmega 328 to communicate with kilobots (a collective robotics platform, all of the information about kilobots is on: www.kilobotics.com).
A summary of how the kilobots work in terms of this project: an external controller uploads a program to the kilobots that tells them what to do. Several capabilities can be uploaded, including the ability to sense distances between one another via infrared transmissions. I want my Arduino to have that capability.
I have successfully created this circuit (scroll down to “Build Your Own Controller” https://www.kilobotics.com/documentation). However, I do not want to upload the program that is listed on the site, which would just make the arduino able to upload programs to the kilobots. Rather, I want my arduino to essentially act like another kilobot. By this I mean that I want the arduino’s IR lights to be able to send commands to the robots.
In order to do this, I am trying to run the kilobot library on my Arduino. GitHub - acornejo/kilolib: Kilobot Library v2). Here is my code so far, note it is just a modified version of ohc.c from the Github kilobot library in the earlier link:

#include <Arduino.h>
#include <stdio.h>
#include <bitfield.h>
#include <debug.h>
#include <kilolib.h>
#include <macros.h>
#include <message.h>
#include <message_buffered.h>
#include <ringbuffer.h>

#include <bootldr.h>
#include <ohc.h>
#include <message_crc.h>
#include <message_send1.h>

#include <avr/io.h> // for port and register definitions
#include <avr/interrupt.h> // for ISR
#include <util/delay.h> // for _delay_ms
#include <string.h> // for memcpy
//#include “ohc.h” // for message definitions
//#include “message_crc.h”
//#include “message_send1.h”
//#include “bootldr.h”

uint8_t packet_buffer[PACKET_SIZE];
uint8_t packet_head = 0;
uint8_t packet_checksum = 0;
uint8_t new_packet[PACKET_SIZE];
volatile uint8_t packet_type;
volatile uint8_t has_new_packet = 0;
//volatile uint8_t tx_mask = 0;
uint8_t leds_toggle = 0;
uint8_t *rawmsg;
message_t msg;
bootmsg_t *bootmsg;
gpsmsg_t *gpsmsg;

#ifdef ARDUINO
#define ir_port PORTB
#define ir_ddr DDRB
#define ir_mask (1<<1)
#define led_port PORTB
#define led_ddr DDRB
#define led_mask (1<<5)
#else
#define ir_port PORTD
#define ir_ddr DDRD
#define ir_mask (1<<3)
#define led_port PORTB
#define led_ddr DDRB
#define led_mask (1<<1)
#endif

uint8_t i;

void setup() {

///
cli();
// Set port outputs
ir_ddr |= ir_mask;
led_ddr |= led_mask;
// Turn off all leds
led_port &= ~led_mask;
ir_port &= ~ir_mask;
// turn off analog comparator (to avoid detecting collisions)
ACSR |= (1<<ACD);

#ifndef ARDUINO
//move interrupt vectors to bootloader interupts
MCUCR = (1<<IVCE);
MCUCR = (1<<IVSEL);
#endif
#ifdef ARDUINO_16MHZ
CLKPR = (1<<CLKPCE);
CLKPR = 1;
#endif

#define BAUD 38400
#include <util/setbaud.h>
UBRR0 = UBRR_VALUE;
#if USE_2X
UCSR0A |= (1<<U2X0);
#else
UCSR0A &= ~(1<<U2X0);
#endif
UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00); // No parity, 8 bits comm, 1 stop bit
UCSR0B |= (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0); // Enable reception, transmission, and reception interrupts
sei();

tx_mask = ir_mask;
bootmsg = (bootmsg_t*)msg.data;
gpsmsg = (gpsmsg_t*)msg.data;
rawmsg = (uint8_t*)&msg;

// Use LEDs to flash power on indicator signal.

for (i=0; i<5; i++) {
led_port |= led_mask;
_delay_ms(200);
led_port &= ~led_mask;
_delay_ms(200);
}
///

}

void loop() {

msg.type = PACKET_FORWARDMSGSINGLE;

if (has_new_packet) {
has_new_packet = 0;
switch(packet_type) {
case PACKET_STOP:
break;
case PACKET_LEDTOGGLE:
leds_toggle = !leds_toggle;
if (leds_toggle) {
led_port |= led_mask;
} else {
led_port &= ~led_mask;
}
break;
case PACKET_FORWARDMSG:
for (i = 0; i<sizeof(message_t)-sizeof(msg.crc); i++)
rawmsg = new_packet[i+2];
msg.crc = message_crc(&msg);
while(!has_new_packet) {
message_send(&msg);
led_port |= led_mask;
_delay_ms(3);
led_port &= ~led_mask;
_delay_ms(3);
}
break;
case PACKET_FORWARDMSGSINGLE:
for (i = 0; i<sizeof(message_t)-sizeof(msg.crc); i++)
rawmsg = new_packet[i+2];
msg.crc = message_crc(&msg);
message_send(&msg);
led_port |= led_mask;
_delay_ms(3);
led_port &= ~led_mask;
_delay_ms(3);
break;
case PACKET_FORWARDRAWMSG:
for (i = 0; i<sizeof(message_t); i++)
rawmsg = new_packet[i+2];
while(!has_new_packet) {
message_send(&msg);
led_port |= led_mask;
_delay_ms(3);
led_port &= ~led_mask;
_delay_ms(3);
}
break;
case PACKET_BOOTPAGE:
msg.type = BOOTPGM_PAGE;
bootmsg->page_address = new_packet[2];
bootmsg->unused = 0;
cli();
for (i = 0; i<SPM_PAGESIZE && !has_new_packet; i+=6) {
bootmsg->page_offset = i/2;
memcpy(&(bootmsg->word1), new_packet+3+i, 6);
msg.crc = message_crc(&msg);
message_send(&msg);
}
sei();
led_port |= led_mask;
_delay_ms(10);
led_port &= ~led_mask;
_delay_ms(10);
break;
#define GPS_MSGSIZE 8
case PACKET_GPSFRAME:
memset(&msg, 0, sizeof(message_t)-sizeof(msg.crc));
msg.type = GPS;
cli();
for (i = 2; i<PACKET_SIZE-GPS_MSGSIZE; i += GPS_MSGSIZE) {
memcpy(gpsmsg, new_packet+i, GPS_MSGSIZE);
if (gpsmsg->id == 0 && gpsmsg->x == 0 && gpsmsg->y == 0 && gpsmsg->theta == 0 && gpsmsg->unused == 0)
break;
msg.crc = message_crc(&msg);
message_send(&msg);
_delay_us(50);
}
sei();
led_port |= led_mask;
_delay_ms(10);
led_port &= ~led_mask;
_delay_ms(10);
break;

}
}

}
ISR(USART_RX_vect) {
uint8_t rx = UDR0;

packet_checksum ^= packet_buffer[packet_head];
packet_buffer[packet_head] = rx;
packet_checksum ^= rx;
packet_head++;
if (packet_head >= PACKET_SIZE)
packet_head = 0;

if (packet_buffer[packet_head] == PACKET_HEADER) {
if (packet_checksum == 0) {
uint16_t i;
uint16_t num = PACKET_SIZE-packet_head;
for (i = 0; i < num; i++)
new_packet = packet_buffer[i+packet_head];
for (i = num; i < PACKET_SIZE; i++)
new_packet = packet_buffer[i-num];
has_new_packet = 1;
packet_type = new_packet[1];
}
}

}

As you can see, the only place where I am actually selecting a communication protocol is the first line in loop():

msg.type = PACKET_FORWARDMSGSINGLE;

This does not work to communicate with the kilobots. Does anyone have any suggestions?

An alternative method that I was trying was to replicate Lab2:Communication (https://www.kilobotics.com/labs#lab2-communication). I have uploaded the listener code to the kilobots, and I am trying to modify the speaker code to get Arduino to run it. Here is my modified code:

#include <kilolib.h>
// declare variables

int led = 13;

uint8_t message_sent = 0;
message_t msg;
void setup() {

pinMode(led, OUTPUT);

// register message_tx function
kilo_message_tx = message_tx;
kilo_message_tx_success = message_tx_success;
// register your program
// kilo_start(setMessage, loop);
msg.type = NORMAL;
msg.crc = message_crc(&msg);

}
void loop() {
// blink when is message sent
if (message_sent) {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
message_sent = 0;
}
}
message_t *message_tx() {
return &msg;
}
void message_tx_success() {
message_sent = 1;
}
//void setMessage(){
// initialize message
// msg.type = NORMAL;
// msg.crc = message_crc(&msg);
//}

I have two tests to check whether or not my code is working.

  1. The arduino built-in LED should blink when a message is sent
  2. The kilobot LED should blink to indicate that it has received a message.

Using this code, neither of those tests pass. Suggestions for this communication method would be appreciated, or if one method seems more feasible than the other.

Suggestions

I suggest that you modify your post to put the code in code tags, not quote tags. I suggest that you select your "links" and add url tags (Insert a link icon).

Links used to be automatic, now they are not. This is one of the features of the improved forum.

Stop “quoting” your code. Put in into code tags.

Please edit your post, select the code, and put it between [code][/code] tags.

You can do that by hitting the # button above the posting area.

Please do not cross-post. This wastes time and resources as people attempt to answer your question on multiple threads.

  • Moderator

I would merge your threads if the forum would let me. Grrrr.

Maybe I'll just delete the other one.

Other thread deleted.

How to use this forum

Read that. It explains about code tags. It talks about cross-posting.

I wonder if the new improved forum lets me ban people temporarily for cross-posting.