Как отправить данные ads1115 через spi на master arduino
Я пытаюсь отправить данные ADS 1115, которые подключены к Arduino mega_1 через I2C, а arduino Mega_1 подключена к arduino Mega_0 через SPI. Arduino Mega_1 действует как ведомое устройство и отправляет данные ADS 1115 на ведущее устройство. Я думаю, что вся моя установка работает, но я хочу получить фактические данные ADS 1115 на мастере Arduino. Вот скриншоты результатов моего кода
мастер
#include <SPI.h>
void setup (void)
{
Serial.begin (9600);
Serial.println ();
digitalWrite(SS, HIGH); // убедиться, что SS пока остается высоким
// Переводим выводы SCK, MOSI, SS в режим вывода
// также переводим SCK, MOSI в состояние LOW, а SS в состояние HIGH.
// Затем переведите оборудование SPI в режим Master и включите SPI.
SPI.begin ();
// Немного замедлить мастер
SPI.setClockDivider(SPI_CLOCK_DIV8);
} // конец настройки
byte transferAndWait (const byte what)
{
byte a = SPI.transfer (what);
delayMicroseconds (20);
return a;
} // конец передачи и ожидания
void loop (void)
{
byte a;
// включить выбор ведомого
digitalWrite(SS, LOW);
transferAndWait ('a'); // добавить команду
a=transferAndWait (0);
// отключаем выбор ведомого
digitalWrite(SS, HIGH);
Serial.println ("results:");
Serial.println (a);
delay (1000); // 1 секундная задержка
} // конец цикла
подчиненный
#include <Wire.h>
#include <Adafruit_ADS1015.h>
int out_buf;
int adc0;
// объявления Adafruit_ADS1115; /* Используйте это для 16-битной версии */
Adafruit_ADS1015 ads;
// что делать с входящими данными
volatile byte command = 0;
void ss_falling ()
{
command = 0;
}
void setup (void)
{
ads.begin();
Serial.begin(9600);
//ads.startComparator_SingleEnded(0, 1000);
// нужно отправить на вход master, *slave на выход*
pinMode(MISO, OUTPUT);
// включаем SPI в ведомом режиме
SPCR |= _BV(SPE);
// включаем прерывания
SPCR |= _BV(SPIE);
attachInterrupt (0, ss_falling, FALLING);
}
// Процедура прерывания SPI
ISR (SPI_STC_vect)
{
byte c = SPDR;
switch (command)
{
// нет команды? тогда это команда
case 0:
command = c;
SPDR = 0;
break;
// добавляем к входящему байту, возвращаем результат
case 'a':
SPDR = out_buf; // добавляем 15
break;
} // конец переключателя
} // конец процедуры обслуживания прерывания (ISR) SPI_STC_vect
void loop (void)
{
adc0 = ads.readADC_SingleEnded(0);
Serial.print("AIN0: "); Serial.println(adc0);
out_buf=adc0;
// int buff = atoi(out_buf);
Serial.print("AIN1: "); Serial.println(out_buf);
delay(1000);
}
я отправляю 1570, но на стороне мастера я получил 35. Я думаю, что данные ADS имеют 16 бит, т.е. 2 байта, а SPI получает только 1 байт за раз. Я застрял здесь, пожалуйста, помогите мне. Заранее спасибо
пример
@Alok Mishra, 👍0
2 ответа
Лучший ответ:
Моя проблема теперь решена, благодаря всемогущему. Я сделал несколько изменений в коде: 1. Преобразование полученных данных типа int из ADS в Char. 2. Сохранил его в массиве, чтобы сформировать строку.
Вот мой модифицированный подчиненный код:
#include <Wire.h>
#include <Adafruit_ADS1015.h>
Adafruit_ADS1015 ads;
void setup (void)
{
ads.begin();
Serial.begin(9600);
// нужно отправить на вход master, *slave на выход*
pinMode(MISO, OUTPUT);
// включаем SPI в ведомом режиме
SPCR |= bit(SPE);
// включаем прерывания
SPCR |= bit(SPIE);
} // конец настройки
char buf[20];
volatile int pos;
volatile bool active;
// Процедура прерывания SPI
ISR (SPI_STC_vect)
{
byte c = SPDR;
if (c == 1) // начинаем новую последовательность?
{
active = true;
pos = 0;
SPDR = buf [pos++]; // отправляем первый байт
return;
}
if (!active)
{
SPDR = 0;
return;
}
SPDR = buf [pos];
if (buf [pos] == 0 || ++pos >= sizeof (buf))
active = false;
} // конец процедуры обслуживания прерывания (ISR) SPI_STC_vect
void loop (void)
{
int adc0=0;
adc0 = ads.readADC_SingleEnded(0);
itoa(adc0,buf,10);
Serial.print("AIN1: "); Serial.println(buf);
delay(500);
} // конец цикла
На стороне мастера
Мы получаем строку, отправляя одно фиктивное значение за раз. Вот модифицированный мастер-код:
#include <SPI.h>
void setup (void)
{
Serial.begin (9600);
Serial.println ("Starting");
digitalWrite(SS, HIGH); // убедиться, что SS пока остается высоким
// Переводим выводы SCK, MOSI, SS в режим вывода
// также переводим SCK, MOSI в состояние LOW, а SS в состояние HIGH.
// Затем переведите оборудование SPI в режим Master и включите SPI.
SPI.begin ();
// Немного замедлить мастер
SPI.setClockDivider(SPI_CLOCK_DIV8);
} // конец настройки
void loop (void)
{
char buf [20];
// включить выбор ведомого
digitalWrite(SS, LOW);
SPI.transfer (1); // инициируем передачу
for (int pos = 0; pos < sizeof (buf) - 1; pos++)
{
delayMicroseconds (15);
buf [pos] = SPI.transfer (0);
if (buf [pos] == 0)
{
break;
}
}
buf [sizeof (buf) - 1] = 0; // обеспечим завершающий нуль
// отключаем выбор ведомого
digitalWrite(SS, HIGH);
Serial.print ("We received: ");
Serial.println (buf);
delay (500);
} // конец цикла
Реализация подчиненного режима SPI немного сложнее, чем вы думаете. Самое важное, что нужно помнить, это то, что это не протокол типа «Дайте мне X» -> «Хорошо, вот X». На самом деле это протокол "Вот X" <=> "Вот Y".
То есть в тот момент, когда ведущий отправляет X подчиненному, подчиненный отправляет "Y" главному.
У вас это так: мастер отправляет «а» в качестве команды и отбрасывает то, что получает. Раб запоминает это «а» как «команду». Затем мастер отправляет 0 и запоминает, что получает. Ведомый получает этот 0 и думает: «А, я получил команду в прошлый раз, поэтому он должен захотеть значение» и ставит значение в очередь для отправки при следующей транзакции. Затем это отбрасывается, поскольку это происходит при отправке следующей «команды».
Вам нужно быть немного хитрее и реализовать конечный автомат, чтобы определить, где вы находитесь в потоке.
- Когда SS падает, установите "счетчик байтов" на 0.
- При получении байта проверьте "счетчик байтов":
- Байт 0: если это "a", поместите первый байт значения в SPDR.
- Байт 1: поместите второй байт значения в SPDR.
- Байт 3: ничего не делать (или поместить 0 в SPDR)
- Увеличить счетчик байтов
Таким образом, транзакция выглядит примерно так (1570 – это 0x622 в шестнадцатеричном формате, и я выбираю "little endian", поскольку AVR, естественно, использует обратный порядок байтов):
Master Sends Slave Queues Master Receives
'a' 0x22 Rubbish
0 0x06 0x22
0 0x00 0x06
'a' 0x22 0x00
0 0x06 0x22
0 0x00 0x06
Важно помнить, что ведущий получает то, что подчиненный поставил в очередь при следующей передаче.
- GSM-модуль IOT-GA6 Arduino + ошибка CME 58
- Разница между массивом char и массивом unsigned char
- Arduino UNO + Ethernet Shield + ЖК-дисплей + RFID, но RFID не работает
- Firmata: как установить определенный PIN на высокий уровень при загрузке?
- Arduino wrap или подкласс print() для работы с несколькими Serial
- Возможно ли, чтобы функция возвращала строку ИЛИ число, в зависимости от адреса
- Считывание данных нескольких датчиков из текстового файла, расположенного на SD-карте в Arduino/ESP32
- Строка в массив динамических байтов
Моя связь SPI работает нормально, потому что я также пробовал сложение и вычитание между ведущим и подчиненным, и результат был «ок»., @Alok Mishra
Если бы ваша spi-связь работала нормально, вы бы не просили нас о помощи..., @Majenko
чувак прочитал эти строки: «Я отправляю 1570, которые являются данными ads1115, но на стороне Master я получил 35, я думаю, что данные ADS имеют 16 бит, то есть 2 байта, а SPI получает только 1 байт за раз». SPI мне подходит .... я думаю, что чего-то не хватает, например, преобразования байтов в символы или разделения 16-битных данных adc на 8 бит, а затем отправки мастеру, это моя настоящая проблема., @Alok Mishra
35 не имеет никакого отношения к 1570. Самое близкое, что вы можете получить, это 34 (0x22). Исправление вашего кода так, как я указываю, не только устраняет беспорядок, который вы создали в системе-отправителе, но также устраняет проблему с 16-битной версией. О, и сделайте свой out_buf изменчивым. Также out_buf должен быть "захвачен" в момент, когда вы либо ставите в очередь первый байт, либо когда SS падает., @Majenko
я добавил еще два скриншота, на которых я отправляю 10, а в ответ получаю 20 "20 = 10 + 10", @Alok Mishra
Это чистая случайность, что *иногда* вы получаете результат, который *считаете* правильным. Это не так. Вы получаете *старые* результаты по *предыдущим* транзакциям, которые *никогда не отправлялись*., @Majenko
хорошо, если я делаю неправильно, то как правильно отправить рекламные данные мастеру arduino с помощью spi, @Alok Mishra
Как я подробно описал в своем ответе., @Majenko