Залізо → Комунікація між arduino nano й cubietruck з використанням модуля nRF24L01+

arduino_nano-cubietruck-nRF24L01

Не так давно виникла ідея зробити невелику «погодну станцію», яка повинна розміщуватися за вікном. Найбільшим бажанням було зробити девайс автономним та без проводів. Про автономність розкажу, коли успішно завершу проект, зараз же поговоримо про «без проводів».

Досвіду роботи з arduino в мене не багато, тому вибирав найдешевший варіант з доступних в українських магазинах, тобто Arduino Nano та приймач/передавач nRF24L01+. Оскільки домашнім сервером у мене уже давно й справно працює Cubietruck, було велике бажання працювати з радіомодулем безпосередньо з нього, а не городити ще одну arduino.

Тестуємо радіомодулі

Перш за все потрібен RF24 драйвер, я використовую форк з деякими фіксами і фічами, можна знайти на github. Підключення по схемі:

Arduino Nano and nRF24L01+nRF24L01+ pins

Код взяв з прикладу передавання положення джойстика, передавач:

#include "SPI.h"
#include "nRF24L01.h"
#include "RF24.h"

#define CE_PIN   9
#define CSN_PIN 10

const uint64_t pipe = 0xE8E8F0F0E1LL;

RF24 radio(CE_PIN, CSN_PIN);

int joystick[2];
int counter = 0;

void setup()
{
  Serial.begin(9600);

  radio.begin();
  radio.openWritingPipe(pipe);
}

void loop()
{
  joystick[0] = counter;
  joystick[1] = counter + 1;
  
  radio.write(joystick, sizeof(joystick));
  counter++;
}

Приймач:

#include "SPI.h"
#include "nRF24L01.h"
#include "RF24.h"

#define CE_PIN   9
#define CSN_PIN 10

const uint64_t pipe = 0xE8E8F0F0E1LL;

RF24 radio(CE_PIN, CSN_PIN);

int joystick[2];

void setup()
{
  Serial.begin(9600);
  delay(1000);
  Serial.println("Nrf24L01 Receiver Starting");

  radio.begin();
  radio.openReadingPipe(1,pipe);
  radio.startListening();
}

void loop()
{
  if (radio.available())
  {
    bool done = false;
    while (!done)
    {
      done = radio.read(joystick, sizeof(joystick));

      Serial.print("X = ");
      Serial.print(joystick[0]);
      Serial.print(" Y = ");      
      Serial.println(joystick[1]);
    }
  }
  else
  {    
      Serial.println("No radio available");
  }
}

У мене все успішно запрацювало з першого разу. Бібліотека RF24 має багато налаштувань, зокрема можна вибрати канал передачі, швидкість, задати розмір пакету, довжину контрольної суми й багато іншого, про все це можна і варто прочитати в інтернетах.

Підключення до cubietruck

Ця частина виявилася найбільш проблемною. Перша проблема — розробники cubietrack дуже економили місце, й замість стандартних роз’ємів з кроком піна 2,54мм поставили 2мм. Вроді дрібниця, але в мене банально не було з чого видерти потрібний роз’єм. Пошукавши, знайшов в китайців, але ціна не тішить.

Про сам процес підключення і супутні проблеми варто почитати на сubieforums в темі nRF24L01. Якщо підсумувати, є декілька портованих бібліотек RF24:

  • Звичайна, від bearpaw (пробував, працює)
  • З підтримкою IRQ від aspinx (не зміг заставити працювати)
  • З підтримкою апаратного CS SPI контролера від UnКаЙF (використовую саме її)

Щоб бібліотека  працювала, потрібно:

1. Ядро з підтримкою SPI. Можна збирати самому, але у моєму дистрибутиві Debian Wheezy така підтримка уже була.

2. Включений SPI в script.bin. Запускаємо команду bin2fex /boot/script.bin /boot/script.fex, в файлі script.fex редагуємо конфіг [spi2_para] та [gpio_para]:

[spi2_para]
spi_used = 1
spi_cs_bitmap = 1
spi_cs0 = port:PC19<3><default><default><default>
spi_sclk = port:PC20<3><default><default><default>
spi_mosi = port:PC21<3><default><default><default>
spi_miso = port:PC22<3><default><default><default>

… … …

[gpio_para]
gpio_used = 1
gpio_num = 4
gpio_pin_1 = port:PH20<1><default><default><1>
gpio_pin_2 = port:PH10<0><default><default><0>
gpio_pin_3 = port:PB18<1><default><default><1>
gpio_pin_4 = port:PB19<1><default><default><1>

GPIO піни слід задавати по порядку, у мене PB19 використовується як CE пін (з 1 по 3 для інших цілей, наразі не потрібно). Після редагування запускаємо зворотню команду fex2bin /boot/script.fex /boot/script.bin та перезавантажуємо систему. якщо все добре, повинен з’явитися пристрій /dev/spidev2.0 (ls /dev/ | grep spi).

3. Правильно підключений модуль nRF24L01+. Я використовував роз’єм CN8

cubietruck-pins

IRQ – none
MISO – PC22 (8)
MOSI – PC21 (6)
CSK – PC20 (7)
CSN – PC19 (5)
CE – PB19 (25)
VCC – VCC-3V (2)
GND – GND (1)

4. Встановлена бібліотека RF24.

Перед тим, як компілювати бібліотеку, перевіряємо чи в файлі /usr/include/linux/spi/spidev.h в структурі spi_ioc_transfer є поле __u16 interbyte_usecs, якщо ні — дописуємо. Далі розпаковуємо завантажений архів з бібліотекою, заходимо в нього й виконуємо команди make, а потім make install.

Тепер все має працювати. Код для тесту, приймач:

#include "cstdlib"
#include "iostream"
#include "gpio.h"
#include "RF24.h"
using namespace std;

typedef struct
{
	int32_t A;
	int32_t B;
	int32_t C;
	int32_t D;
	int32_t E;
	int32_t F;
	int32_t G;
	uint8_t Device;
	uint8_t Packet;
}
Packet_t;
Packet_t data;

const uint64_t myPipe = 0xE8E8F0F0E1LL;

RF24 radio(SUNXI_GPB(19), "/dev/spidev2.0");

void setup(void)
{
	printf("Nrf24L01 Receiver Starting\n");
	radio.begin();
	radio.setChannel(0);
	radio.openReadingPipe(1, myPipe);
	radio.startListening();
}

void loop(void)
{
	if ( radio.available() )
	{
		bool done = true;
		while (done){
			uint8_t len = radio.getDynamicPayloadSize();
			done = !radio.read(&data, len);
			printf("Device: %d, Packet: %d, A: %d, B: %d, C: %d, D: %d, E: %d, F: %d, G: %d\n", data.Device, data.Packet, data.A, data.B, data.C, data.D, data.E, data.F, data.G);
		}
	}
	usleep(1000000);
}

int main(int argc, char** argv)
{
	setup();
	while(1) loop();

	return 0;
}

Передавач:

#include "SPI.h"
#include "nRF24L01.h"
#include "RF24.h"

#define CE_PIN	 9
#define CSN_PIN 10

typedef struct
{
	int32_t A;
	int32_t B;
	int32_t C;
	int32_t D;
	int32_t E;
	int32_t F;
	int32_t G;
	uint8_t Device;
	uint8_t Packet;
}
Packet_t;
Packet_t data;

const uint64_t pipe = 0xE8E8F0F0E1LL;
const uint32_t device = 10;

RF24 radio(CE_PIN, CSN_PIN);

void setup()
{
	Serial.begin(9600);
	
	radio.begin();
	radio.setChannel(0);
	radio.openWritingPipe(pipe);
}

unsigned long count = 30000;

void loop()
{
	Serial.println(count);
	data.Device = 10;
	data.Packet = 2;
	data.A = count;
	data.B = count+1;
	data.C = count+2;
	data.D = count+3;
	data.E = count+4;
	data.F = count+5;
	data.G = count+6;

	radio.write(&data, sizeof(data));
	Serial.println(count);
	
	count++;
	delay(5000);
}

Лінки

.

06.06.2015 23:50 Автор: Strange_V Хіти: 889

Пінгбеки заборонені, лише коментарі.

Напишіть відгук