Взаимодействие AD7606 с Arduino Due. Как вести журнал данных?

У меня 16-битный АЦП7606. Это в параллельном режиме. У меня есть рабочий скетч, который позволяет мне читать 8 каналов, преобразовывать 16-битное целое число в десятичное, а затем печатать последовательные данные для мониторинга. Я хотел бы увеличить частоту дискретизации. Последовательный монитор не может поддерживать частоту дискретизации выше 40 миллис. Due подключается через USB на COM3.

Как записать данные в файл на моем ноутбуке/компьютере?

Мы будем очень признательны за любую помощь.

Код ниже

#include <EnableInterrupt.h>

#define BUSY 3
#define RD 4  //RD+CS tied together
#define RESET 5
#define CONVST 6 //CONVSTA+CONVSTB soldered together on the board
#define RANGE 7

#define DB0 38
#define DB1 39
#define DB2 40
#define DB3 41
#define DB4 42
#define DB5 43 
#define DB6 44
#define DB7 45
#define DB8 46
#define DB9 47
#define DB10 48
#define DB11 49
#define DB12 50
#define DB13 51
#define DB14 52
#define DB15 53

// declare rawData as an array of 16 integers
int rawData[16];

void setup() {

  enableInterrupt(BUSY, ISR_, FALLING);

  pinMode(RESET, OUTPUT);
  pinMode(CONVST, OUTPUT);
  pinMode(RD, OUTPUT);
  pinMode(RANGE, OUTPUT);
  pinMode(BUSY, INPUT);

  Serial.begin(9600);

  //reset ADC to begin conversion 
  digitalWrite(RESET, HIGH);
  delayMicroseconds(10);
  digitalWrite(RESET, LOW);

  digitalWrite(CONVST, LOW);  
  digitalWrite(RD, HIGH);
  digitalWrite(RANGE, HIGH);
  digitalWrite(BUSY, LOW);  

  delayMicroseconds(1000);

}

void loop() {

  disableInterrupt(BUSY);

  delayMicroseconds(40000); 
  digitalWrite(CONVST, LOW);
  delayMicroseconds(10); 
  digitalWrite(CONVST, HIGH);
  enableInterrupt(BUSY, ISR_, FALLING);

}

void ISR_ ()  {

  //Serial.print(millis());
  //Serial.print(",");

  delayMicroseconds(1);
  digitalWrite(RD, LOW);
  delayMicroseconds(1);
  readDBpins(); // do read
  digitalWrite(RD, HIGH);
  Serial.print(",");

  delayMicroseconds(1);
  digitalWrite(RD, LOW);
  delayMicroseconds(1);
  readDBpins(); // do read
  digitalWrite(RD, HIGH);
  Serial.print(",");

  delayMicroseconds(1);
  digitalWrite(RD, LOW);
  delayMicroseconds(1);
  readDBpins(); // do read
  digitalWrite(RD, HIGH);
  Serial.print(",");

  delayMicroseconds(1);
  digitalWrite(RD, LOW);
  delayMicroseconds(1);
  readDBpins(); // do read
  digitalWrite(RD, HIGH);
  Serial.print(",");

  delayMicroseconds(1);
  digitalWrite(RD, LOW);
  delayMicroseconds(1);
  readDBpins(); // do read
  digitalWrite(RD, HIGH);
  Serial.print(",");

  delayMicroseconds(1);
  digitalWrite(RD, LOW);
  delayMicroseconds(1);
  readDBpins(); // do read
  digitalWrite(RD, HIGH);
  Serial.print(",");

  delayMicroseconds(1);
  digitalWrite(RD, LOW);
  delayMicroseconds(1);
  readDBpins(); // do read
  digitalWrite(RD, HIGH);
  Serial.print(",");

  delayMicroseconds(1);
  digitalWrite(RD, LOW);
  delayMicroseconds(1);
  readDBpins(); // do read
  digitalWrite(RD, HIGH); 

  Serial.println(" ");

}

void readDBpins()
{
  rawData[0] = digitalRead(DB15);
  //Serial.print (rawData[0]);
  if (rawData[0] > 0) {rawData[0] = 32768;} 
  rawData[1] = digitalRead(DB14);  
  //Serial.print (rawData[1]);
  if (rawData[1] > 0) {rawData[1] = 16384;}
  rawData[2] = digitalRead(DB13);
  //Serial.print (rawData[2]);
  if (rawData[2] > 0) {rawData[2] = 8192;}
  rawData[3] = digitalRead(DB12);
  //Serial.print (rawData[3]);
  if (rawData[3] > 0) {rawData[3] = 4096;}
  rawData[4] = digitalRead(DB11);
  //Serial.print (rawData[4]);
  if (rawData[4] > 0) {rawData[4] = 2048;}
  rawData[5] = digitalRead(DB10);
  //Serial.print (rawData[5]);
  if (rawData[5] > 0) {rawData[5] = 1024;}
  rawData[6] = digitalRead(DB9);
  //Serial.print (rawData[6]);
  if (rawData[6] > 0) {rawData[6] = 512;}
  rawData[7] = digitalRead(DB8);
  //Serial.print (rawData[7]);
  if (rawData[7] > 0) {rawData[7] = 256;}
  rawData[8] = digitalRead(DB7);
  //Serial.print (rawData[8]);
  if (rawData[8] > 0) {rawData[8] = 128;}
  rawData[9] = digitalRead(DB6);
  //Serial.print (rawData[9]);
  if (rawData[9] > 0) {rawData[9] = 64;}
  rawData[10] = digitalRead(DB5);
  //Serial.print (rawData[10]);
  if (rawData[10] > 0) {rawData[10] = 32;}
  rawData[11] = digitalRead(DB4);
  //Serial.print (rawData[11]);
  if (rawData[11] > 0) {rawData[11] = 16;}
  rawData[12] = digitalRead(DB3);
  //Serial.print (rawData[12]);
  if (rawData[12] > 0) {rawData[12] = 8;}
  rawData[13] = digitalRead(DB2);
  //Serial.print (rawData[13]);
  if (rawData[13] > 0) {rawData[13] = 4;}
  rawData[14] = digitalRead(DB1);
  //Serial.print (rawData[14]);
  if (rawData[14] > 0) {rawData[14] = 2;}
  rawData[15] = digitalRead(DB0);
  // Serial.print (rawData[15]);
  if (rawData[15] > 0) {rawData[15] = 1;}

  Serial.print (rawData[0]+rawData[1]+rawData[2]+rawData[3]+rawData[4]+rawData[5]+rawData[6]+rawData[7]+rawData[8]+rawData[9]+rawData[10]+rawData[11]+rawData[12]+rawData[13]+rawData[14]+rawData[15]);
}

, 👍0

Обсуждение

Его название AD7606 (без C)? http://www.analog.com/en/products/ad7606.html, @Jot

почему 9600 бод? попробуйте 921600 бод, @Juraj

Другие программы последовательного терминала могут иметь функцию сохранения полученных данных в файл. Попробуйте некоторые из них. И - поскольку последовательный интерфейс не справляется - как написал Юрай, увеличьте скорость передачи данных, чтобы передача данных происходила с большей скоростью., @chrisl

Спасибо, ребята. Я читал, что все, что выше 115200 бод, неэффективно. 115200 — это обычная скорость, которую я использую. Serial Monitor не может отображать показания с частотой дискретизации выше 40 миллисекунд, поэтому я не могу сделать то, что я обычно делаю, а именно скопировать и вставить в файл, поскольку копировать там нечего., @Microk

@Juraj и chrisl 921600 бод и все, что выше 250000, выводит тарабарщину. Теперь у меня есть скрипт журнала pyserial, но он все еще узкие места, хотя теперь на 1,5 миллис, что хорошо, но недостаточно. Теперь я знаю, что испортил преобразование дополнения до 2 в моем скетче arduino, но даже с комментарием он все еще узкие места., @Microk


1 ответ


Лучший ответ:

2

Вы можете использовать Python в командной строке для регистрации вывода последовательного монитора. Это описано здесь. В приведенном ниже сценарии скорость передачи данных составляет 250000, но ее можно установить в соответствии с тем, как вы программируете свой Arduino.

from time import sleep
import serial

# Change port and baud rate to match your setup
ser = serial.Serial('/dev/ttyACM0', 250000) # Establish the connection on a specific port

counter = 32 # Below 32 everything in ASCII is gibberish

while True:
     counter +=1
     ser.write(str(chr(counter))) # Convert the decimal number to ASCII then send it to the Arduino
     print(ser.readline()) # Read the newest output from the Arduino
     sleep(.1) # Delay for one tenth of a second
     if counter == 255:
         counter = 32

Скрипт взят здесь. Вы должны указать соответствующий порт и скорость передачи данных. Эта ссылка Mathworks описывает как узнать номер порта.

  • В Windows найдите в диспетчере устройств раздел «Последовательный порт USB».
  • В Linux или OSX откройте терминал и выполните поиск с помощью ls /dev/* или ls /dev/tty*. Вы можете | grep <search> в той же строке для поиска по usb или ACM

Это обсуждение максимальной скорости передачи данных. Я увеличил значение 250000 на программном порте Due, но вы можете работать быстрее, используя собственный порт. Вы также можете быть ограничены USB-портом вашего компьютера, хотя это маловероятно. Максимум 480 Мбит/с для USB 2.0.

Arduino Due имеет два порта USB. Собственный порт USB (который поддерживает последовательную связь CDC с использованием объекта SerialUSB) подключается напрямую к микроконтроллеру SAM3X. Другой порт USB Программный порт. Он подключен к ATMEL 16U2, который действует как Конвертер USB-Serial. Этот порт программирования используется по умолчанию для загрузка скетчей и общение с Arduino.

Конвертер USB-последовательный порт программирования подключен к первый UART SAM3X. По этому поводу можно общаться порт, используя объект «Serial» на языке программирования Arduino.

Разъем USB собственного порта напрямую подключен к USB-разъему. хост-контакты SAM3X. Использование собственного порта позволяет использовать В качестве клиентского периферийного USB-устройства (действующего как мышь или клавиатура) подключен к компьютеру) или в качестве хост-устройства USB, чтобы устройства могли быть подключен к Due (например, мышь, клавиатура или телефон Android). Этот порт также можно использовать как виртуальный последовательный порт, используя команду Объект «SerialUSB» на языке программирования Arduino.

Из руководства по Arduino Due вы можете переключить Serial.print на >SerialUSB.print, то же самое и с другими последовательными функциями, такими как println. Затем, если вы подключите USB-накопитель к собственному порту, вы сможете считывать данные с этого порта с более высокой скоростью передачи данных. Вы также должны инициализировать SerialUSB,

SerialUSB.begin(2000000);    // Инициализируем собственный USB-порт
while(!SerialUSB);           // Подождем, пока соединение установится

Не имеет значения, какую скорость передачи данных вы установили на собственном порту, он будет работать на максимальной скорости шины, но, насколько я знаю, ее нужно устанавливать в любом случае.

При работе в командной строке вы можете использовать > для отправки вывод в файл журнала.

Например,

python serial_log.py > out.txt
,

Спасибо за подробный ответ. Теперь у меня есть базовый вывод эскиза, который считывается python и отображается в окне командной строки python. Теперь я могу регистрировать данные благодаря пути, который вы мне указали, используя другой скрипт последовательного регистратора, который я нашел здесь https://github.com/diegoherranz/serial-logger, @Microk

Я не смог заставить serial_log.py, который вы предложили, работать. У меня все еще та же проблема, я регистрирую 8 столбцов 16-битных целых чисел с большей скоростью, чем 40 миллис. Как вы думаете, ваше предложение сможет регистрировать быстрее?, @Microk

Я считаю, что предоставленный код работает только с python2. Если у вас есть что-то похожее, это тоже хорошо. Повышение скорости передачи данных увеличит скорость передачи данных, [примечания о скорости передачи данных](https://learn.sparkfun.com/tutorials/serial-communication/rules-of-serial). Скрипт python может включать скорости передачи данных, которые arduino ide не поддерживает. Если ваша проблема на самом деле связана со скоростью функции arduino, вы можете рассмотреть альтернативу, [это пример для функции analogRead](http://nicecircuits.com/playing-with-analog-to-digital-converter-on-arduino-due/)., @jmb2341

Обновление: при 250000 бод я могу увеличить частоту дискретизации до 2 миллис, что хорошо, но мне нужно минимум 1 миллис, а в идеале я бы достиг 0,5 миллис. Я знаю, что есть скорости 500k и 1M бод, но все, что выше 250k бод, возвращает бессмыслицу. Должен быть способ считывать 16 цифровых выводов 8 раз подряд и регистрировать результат каждые 0,5 мс....., @Microk

Используйте собственный порт и увеличьте скорость передачи данных еще больше. Замените Serial.print на SerialUSB.print, см. обновленный ответ., @jmb2341

Реализовано! Due не может решить, подключен ли он к порту 5 или 6. Я могу загрузить скетч, но pyserial logger не может получить доступ к порту, и serial monitor тоже. Для меня уже почти полночь, так что, думаю, мне придется оставить это на завтра, если я смогу поспать, то есть я чувствую, что нахожусь на грани прорыва! Ура, @Microk

Убедитесь, что вы получаете доступ к последовательному порту только из одного места. Если у вас есть Arduino ide, получающая доступ к монитору, то вы не сможете использовать скрипт для доступа к нему, или если у вас открыты два окна терминала. Также я бы, вероятно, все равно программировал через порт программирования, а затем переключился на собственный порт для чтения. Надеюсь, это поможет!, @jmb2341

Вы попали в точку! программа в порту программирования, запустите регистратор pyserial в родном порту USB, и я в шоке! Поигравшись со своим эскизом, я теперь считываю в среднем 1 миллисекунду. Я верю, что смогу сократить время обработки, настроив свой эскиз и найдя более рациональный способ считывания 16-разрядных выводов, преобразования в dec, а затем печати. НО проблема быстрой записи данных в файл на моем компьютере/ноутбуке решена, вопрос полностью решен. Я очень благодарен за ваше время и вашу помощь. Спасибо!, @Microk