Ksercsis

Совет по подключению счётчиков Гейгера

17 сообщений в этой теме

Ksercsis    1

Здравствуйте. Решил собрать дозиметр на микроконтроллере. Решил соединить сразу 4 счётчика.  Нашел в Интернете две схемы с разным соединением. Прошу совета. Может кто уже этим занимался. Какая схема лучше?

3.png

575c1ec53ef14426832d5885a98b72ed.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Быстрый заказ печатных плат

Полный цикл производства PCB по низким ценам!

  • x
    мм
Заказать Получить купон на $5.00
oldmao    1 216

А с какого перепугу на сайте для начинающих должны знать подробности метрологии ядерной физики? Ищите ответы в старых (выпущенных до 90-х) учебниках по радиометрии. Я бы начал именно с поиска таких книг.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Ksercsis    1

А причём метрология ядерной физики? Здесь стоит вопрос о соединении сигналов с 4 счётчиков в один выход сигналов.  На первой схеме счётчики соединены параллельно, а  на второй они подключены через транзистор.  Поэтому и возник спор.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
oldmao    1 216

Ты не поверишь - на второй они тоже параллельно. И работают они тоже с одинаковой ошибкой: если при срабатывании одного счётчика сработает другой (в то время, пока не произошло самогашение разряда в первом), то на выходе вместо двух импульсов получим один, но бОльшей длительности. В приборах, работающих по принципу счётчиков импульсов, это приведёт к занижению показаний. К счастью, при фоновой радиации это несущественно, а вот при превышении фона в десятки раз - прибор уже существенно врёт. Надеюсь, ваш прибор будет мерять только продукты с рынка, тогда не забивайте голову и делайте по первой схеме, вторая неоправданно усложнена.
А вот ответ на ваш вопрос я вычитал лет двадцать восемь тому назад как раз в старом армейском учебнике...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
colorad    224
51 минуту назад, Ksercsis сказал:

А причём метрология ядерной физики?

Не совсем понятно зачем надо 4 счетчика  без профильного образования .

Поставьте 4 шт . по отдельности, как в 1-й схеме к разным портам МК  . Будет возможность анализировать данные с каждого счетчика отдельно и со всех вместе .

Радиационный  фон может быть разный в течении суток , мерить его все одно надо длительное время . Может 1-го достаточно ? Промышленные решения с 4 шт-ми есть ?

Изменено пользователем colorad

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
dm37    54

4 штуки включаются в параллель как раз для повышения чувствительности, и анализируют как количество импульсов так и длину. Правильнее сказать анализируют площадь за единицу времени (постоянная времени), потом делят на 4. Причём постоянная времени должна меняться в зависимости от уровня излучения. Подавать на микроконтроллер сырой сигнал может не получиться, как правило ставиться обработка на операционниках (в интегральном включении), а на микроконтроллер (лучше DSP) подают либо частоту, либо уровень, пропорционально излучению, кому что нравиться.

Изменено пользователем dm37

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Гость Тим   
Гость Тим

найдите паспорт на СБТ 10 и 11 там была схема подключения с конденсаторами на 10 пик по моему.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
next sound    62

таки правильная рекомендация - каждый прибор на свой вход МК

а далее математика

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Ksercsis    1

Спасибо за советы! Да нет, продукты им точно мерять не буду. В кабинет физики нужен для лабораторных работ. Детали есть, пока делаю наброски на схему.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
IMXO    1 056
3 часа назад, oldmao сказал:

В приборах, работающих по принципу счётчиков импульсов, это приведёт к занижению показаний. К счастью, при фоновой радиации это несущественно, а вот при превышении фона в десятки раз - прибор уже существенно врёт.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Ksercsis    1

Про зашкал я уже знаком. Блин, я дурак. Можно и вправду ведь подключить каждый счётчик к отдельному порту микроконтроллера. Если их подключить по отдельности, то если частицы попадут в два счётчика одновременно, то микроконтроллер засчитает как два сигнала а не один длиный.  Это может снизить риск занижения показаний. Тогда подойдёт первая схема, если к каждому счётчику добавить  транзистор.

15 часов назад, oldmao сказал:

Ты не поверишь - на второй они тоже параллельно. И работают они тоже с одинаковой ошибкой: если при срабатывании одного счётчика сработает другой (в то время, пока не произошло самогашение разряда в первом), то на выходе вместо двух импульсов получим один, но бОльшей длительности. В приборах, работающих по принципу счётчиков импульсов, это приведёт к занижению показаний. К счастью, при фоновой радиации это несущественно, а вот при превышении фона в десятки раз - прибор уже существенно врёт. Надеюсь, ваш прибор будет мерять только продукты с рынка, тогда не забивайте голову и делайте по первой схеме, вторая неоправданно усложнена.
А вот ответ на ваш вопрос я вычитал лет двадцать восемь тому назад как раз в старом армейском учебнике...

 

Изменено пользователем Ksercsis

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
colorad    224
3 минуты назад, Ksercsis сказал:

то микроконтроллер засчитает как два сигнала а не один длиный.

Длинный можно засчитать как два программно , а если между двумя втиснется третий  , то будет неясно - есть он или нет .

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Ksercsis    1
Только что, colorad сказал:

Длинный можно засчитать как два программно , а если между двумя втиснется третий  , то будет неясно - есть он или нет .

Да, будет комфликт

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Ksercsis    1
8 минут назад, next sound сказал:

на отдельные порты

а далее МАТЕМАТИКА, господа - математика!!!

Конечно, математика. А иначе как?!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ваша публикация должна быть проверена модератором

Гость
Вы не авторизованы. Если у вас есть аккаунт, пожалуйста, войдите.
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Восстановить форматирование

  Разрешено не более 75 смайлов.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

Загрузка...

  • Похожие публикации

    • Автор: Aven
      Появилась необходимость собрать устройство на базе Arduino, которое работает с SD картой.
      Так как работа от аккумулятора, нужно максимально снизить ток потребления.
      Возникла проблема, если отключить питание SD карты, чтобы уйти в сон, после его возобновления работа с картой уже невозможна, при попытке пере инициализировать все виснет.
      Вопрос, как лучше реализовать отключение SD карты?
    • Автор: carlogulliani
      Добрый день!
      Столкнулся с такой проблемой, пытаюсь взаимодействовать с чипом AFE4300 по SPI. В дотащите указано, что уровень сигнала 2 - 3 вольта. Подключаю к nrf51 (использует уровень 3.3 вольта), ресетю и пытаюсь прочитать дефолтное значение регистра (0x01C3), в итоге получаю 0xFFFF.
      Перепроверил на Arduino Mega 2560, где уровень сигнала 5 вольт (подключил напрямую без level shifter) и считал свои дефолтные значения. Попробовал также считать другие 4 регистра, все также отлично считалось.
      Вот теперь не пойму, в дотащите указано не верно или у меня что-то не то.
      Еще вопрос про согласовать уровней TXB0108. Пытался через нее прокинуть сигнал от nrf51 (3.3v) на afe4300. Питание А - 3.3в, каналы А к nrf51, питание Б 5в, каналы Б к afe4300, OE к 3.3в. Не завелось, даже анализатор говорит, что MOSI шлет 0xFF, вместо реальных данных. Земля везде общая.
      Правда есть оговорка, как данный уровень ко мне приехал я мог по ошибке запитать Б 3 вольтами, а А 5 вольтами. Но даташит на него говорит, что когда А > Б, это не повреждает чип, хотя А должно быть до 3.6 вольт. Еще мог OE подключить к 5 вольтам. В общем, могли ли мои неразумные операции вывести его из строя???
       
      Еще в даташите указано, что неиспользуемые каналы надо подключить либо к питанию, либо к земле. Это может влиять на то, что я сейчас получаю?
    • Автор: mefi73
      Эта статья является логическим продолжением  вот этой статьи про монохромный OLED дисплей. На этот раз мне в руки достался цветной OLED дисплей, разрешением 96*64 пикселя от магазина Banggood (ссылка на дисплей) Пока не забыл, на странице товара есть ссылка на архив с документацией на дисплей.
      Кроме того достаточно информации по дисплею встречается в сети, так же есть готовые библиотеки для нетерпеливых (от Adafruit, Seeed-Studio и конечно же монстр среди библиотек для дисплеев U8Glib). Я же покажу работу с дисплеем безо всяких библиотек, покажу в среде программирования ArduinoIDE, что бы было понятно новичкам (матерые программисты наверняка разберутся).
      Итак, дисплей может подключаться при помощи параллельных интерфейсов (6800, 8080) и последовательного интерфейса SPI. В модуле, который попал мне в руки, реализован SPI протокол.

      Распиновка слева-направо: 2 вывода для питания, SCL - предназначен для тактового сигнала, SDA - по этому входу в контроллер дисплея поступают данные, RES - предназначен для сброса дисплея, DC (data/command) - логический сигнал на этом входе сообщает дисплею что в данный момент передается, данные или команда (об этом чуть позже подробнее), CS - обычный chip select протокола SPI, низкий уровень на этом входе сообщает дисплею, что данные, поступающие по нему, предназначены именно для дисплея. Подробно вдаваться в суть протока SPI я не буду, стоит только уточнить, что дисплей работает в режиме SPI_MODE3 (CPOL=1, CPHA=1).
      Вас могут смутить обозначения SDA и SCL, ведь они применяются для обозначения выводов устройств, работающих по протоколу I2C, но всё на самом деле не так плохо. Поскольку по линии SDA идут данные от микроконтроллера к дисплею - он подключается к выводу MOSI микроконтроллера (D11 на ардуино). По SCL идут тактовые сигналы, а значит он подключается к выводу SCK микроконтроллера (D13 на ардуино).
      Для выводов RES, DC и CS можно выбрать любые выводы (у меня D10 для CS, D8 для DC и  D9 для RES). Библиотека SPI не будет управлять этими выводами, это придется делать вручную. Разберемся для чего нужен каждый из этих выводов.
      CS - самое простое, логический 0 говорит дисплею о том, что данные предназначены для него, логическая 1 - о том что передача данных завершена.
      RES - служит для сброса дисплея, для этого надо на некоторое время подать на этот вывод логический 0. Это необходимо сделать один раз в начале программы перед инициализацией дисплея.
      DC - логический 0, подаваемый на этот вывод, сообщает дисплею о том, что передаются команды, логическая 1 - передаются данные.
      На основании этого создаем две функции для отправки команды и данных соответственно. 
      #include <SPI.h> const int ss = 10; //slave select const int dc = 8; // data/command data=1 command=0 const int reset = 9; //oled reset=0 void oledCommand(uint8_t val) //общая функция отправки команды дисплею {   digitalWrite(ss, LOW); //slave select устанавливаем в 0, это активирует SPI   digitalWrite(dc, LOW); //DC равен 0, это значит что отправляется команда   SPI.transfer(val); //отправляем команду стандартной функцией библиотеки SPI   digitalWrite(ss, HIGH); //slave select устанавливаем в 1, это означает что работа с SPI завершена } void oledData(uint8_t val) //общая функция отправки данных дисплею {   digitalWrite(ss, LOW); //slave select устанавливаем в 0, это активирует SPI   digitalWrite(dc, HIGH); //DC равен 1, это значит что отправляются данные   SPI.transfer(val); //отправляем данные стандартной функцией библиотеки SPI   digitalWrite(ss, HIGH); //slave select устанавливаем в 1, это означает что работа с SPI завершена } void setup() {  pinMode(ss, OUTPUT);  pinMode(dc, OUTPUT);  pinMode(reset, OUTPUT);  SPI.begin();  SPI.setDataMode(SPI_MODE3);  oledInit(); } void setup() {  pinMode(ss, OUTPUT);  pinMode(dc, OUTPUT);  pinMode(reset, OUTPUT);  SPI.begin();  SPI.setDataMode(SPI_MODE3);  oledInit(); } Обратите внимание на функция oledInit() в предпоследней строке кода. Прежде чем дисплей сможет что-либо выводить на экран, его необходимо настроить (инициализировать). Для этого посылаем команды, приведенные в следующей диаграмме.

      init.PNG
      В программе это будет выглядеть так:
      void oledInit() //функция инициализации дисплея {   digitalWrite(reset, HIGH); //процедура сброса дисплея   delay(100);   digitalWrite(reset, LOW);   delay(100);   digitalWrite(reset, HIGH);   delay(100);   //процедура инициализации дисплея   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0xAE); //display OFF   SPI.transfer(0xA0); //remap & color depth setting   SPI.transfer(0x72);          //b01110010 расшифровка ниже   /*   b01 - 65k format, (00 -256 color, 10 - 65k color format 2)   1 - enable COM split odd even (0 - disable)   1 - scan COM95 to COM0 (0 - COM0 to COM95) отражение по короткой стороне   0 - disable left-right swaping (1 - enable swaping)   0 - RGB color (1 - BGR color)   1 - RAM column 0 to 95 (0 - 95 to 0)   0 - horizontal address increment (1 - vertical)   */   SPI.transfer(0xA1); //set display start line (0-63)   SPI.transfer(0x0);   SPI.transfer(0xA2); //set vertical offset (0-63)   SPI.transfer(0x0);   SPI.transfer(0xA4); //normal display (A5 - all pixel ON, A6 - all pixel OFF, A7 - inverse display)   SPI.transfer(0xA8); //set MUX ratio N+1 mux   SPI.transfer(0x3F); //default 0x3F   SPI.transfer(0xAD); //select internal Vcc supply   SPI.transfer(0x8E); //default 0x8E   SPI.transfer(0xB0); //set power saving mode   SPI.transfer(0x0B); //default 0x0B (disable power saving mode) 0X1A - enable   SPI.transfer(0xB1); //set reset, pre-charge period   SPI.transfer(0x31); //default 0x31   SPI.transfer(0xB3); //oscillator frequency   SPI.transfer(0xF0); //default 0xF0   SPI.transfer(0x8A); //set second pre-charge color A   SPI.transfer(0x64); //default 0x64   SPI.transfer(0x8B); //set second pre-charge color B   SPI.transfer(0x78); //default 0x78   SPI.transfer(0x8C); //set second pre-charge color C   SPI.transfer(0x64); //default 0x64   SPI.transfer(0xBB); //set pre-charge voltage level   SPI.transfer(0x3A); //default 0x3A   SPI.transfer(0xBE); //set COM deselect voltage level   SPI.transfer(0x3E); //default 0x3E   SPI.transfer(0x87); //set master current   SPI.transfer(0x06); //default 0x06   SPI.transfer(0x81); //set contrast for color A   SPI.transfer(0x91); //default 0x91   SPI.transfer(0x82); //set contrast for color B   SPI.transfer(0x50); //default 0x50   SPI.transfer(0x83); //set contrast for color C   SPI.transfer(0x7D); //default 0x7D   SPI.transfer(0xAF); //display ON, normal mode   digitalWrite(ss, HIGH); } Теперь дисплей готов к выводу изображения. Но стоит рассмотреть некоторые команды. В частности очень важны следующие строки:
      SPI.transfer(0xA0); //remap & color depth setting
      SPI.transfer(0x72); //b01110010 расшифровка ниже
      /* b01 - 65k format, (00 -256 color, 10 - 65k color format 2) - здесь мы выбираем в каком формате будут задаваться цвета и сколько цветов будет возможно использовать
      Поскольку выбираем 65 тысяч цветов, то значение цвета в один байт не поместится, только в два байта.
      1 - enable COM split odd even (0 - disable)
      1 - scan COM95 to COM0 (0 - COM0 to COM95) отражение по короткой стороне
      0 - disable left-right swaping (1 - enable swaping) 0 - RGB color (1 - BGR color) задаем привычный нам формат RGB
      1 - RAM column 0 to 95 (0 - 95 to 0)
      0 - horizontal address increment (1 - vertical) */ Выбираем как будут выводиться данные на дисплей, слева-направо сверху-вниз (привычный нам способ, потому что и пишем так и массивы задаем) или сверху-вниз слева-направо. Эти методы адресации рассмотрены в предыдущей статье, лишь отмечу что мы будем использовать горизонтальную адресацию.
      Поскольку для задания цвета у нас есть всего 2 байта, а формат RGB предполагает 3, то необходимо произвести преобразование. Для красного цвета отводятся первые 5 бит, затем 6 бит зеленого цвета, замыкают 5 бит синего, поэтому функцию преобразования цвета я назвал color565
       
       uint16_t c;   c = r >> 3;   c <<= 6;   c |= g >> 2;   c <<= 5;   c |= b >> 3;   return c;// получаем 16-битное значение цвета и возвращаем его } Поскольку данными необходимо передавать только цвет, то функцию передачи данных можно переделать в функцию передачи цвета, но 16-битное значение цвета необходимо будет разбить на два 8-битных и послать их одно за другим.
      void oledDataColor(uint16_t color) //измененная функция для отправки 16-битного значения цвета {   digitalWrite(ss, LOW);   digitalWrite(dc, HIGH);   SPI.transfer(color >> 8); //разбиваем 16-битное значение на 2 8-битных   SPI.transfer(color);   digitalWrite(ss, HIGH); } Теперь можно рисовать, и начну я с базового элемента любого растрового изображения - пикселя. Для отображения графических примитивов предусмотрены готовые функции, но не для пикселя и окружности, поэтому будем изобретать велосипед.
      Я упоминал про горизонтальную адресацию, команды и данные, и сейчас я свяжу это всё воедино и поведаю как вывести изображение на дисплей (но делать я этого конечно же не буду).
      Представим, что необходимо вывести изображение размером N на N пикселей, левый верхний угол изображения должен находиться в координатах х=X, у=Y. Для этого необходимо выбрать прямоугольную область на дисплее, а затем передать значения цвета пикселей по очереди обходя каждый пиксель изображения слева-направо сверху-вниз. Полученные дисплеем значения цвета так же будут выводиться слева-направо сверху-вниз в пределах выбранной области, и обход пикселей будет таким, как представлен на изображении ниже.

      Для выбора области на дисплее необходимо передать команду 0x15,значения Х и У левого верхнего угла области, затем команду 0x75 и значения Х и У правого нижнего угла области. Все эти значения передаются командами, то есть вывод DC подтянут к нулю. Затем подаем на DC логическую единицу и посылаем значения цвета каждого пикселя. Функции отправки команд, данных и цвета я уже привел. Далее необходимо включить фантазию и принять факт что один пиксель - это изображение состоящее из одного пикселя, и процедуру вывода изображения применить к одному единственному пикселю. В итоге получается вот такая функция:
      //функция задает цвет выбранной точке void oledPixel(uint8_t x, uint8_t y, uint16_t color) {   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0x15);   SPI.transfer(x);   SPI.transfer(95);   SPI.transfer(0x75);   SPI.transfer(y);   SPI.transfer(63);   delay(1);   digitalWrite(dc, HIGH);   SPI.transfer(color >> 8);   SPI.transfer(color);   delay(1);   digitalWrite(ss, HIGH); } Далее пойдут уже готовые функции для вывода линии, прямоугольника и залитого прямоугольника. 
      //функция отрисовывает линию определенного цвета между двумя указанными координатами void oledLine (uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t color) {   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0x21);   SPI.transfer(x1); //x start   SPI.transfer(y1); //Y start   SPI.transfer(x2); //X end   SPI.transfer(y2); //Y end   delay(1);   //здесь синтезированный в формат 565 цвет разбирается отбратно   //я понимаю что это костыль, но во первых для задания цвета необходимо использовать один аргумент вместо трех   //а во вторых, я использовал именно такой способ для общего понимания работы с цветом при работе с данным дисплеем   SPI.transfer((color >> 11) & 0x1F); //R color   SPI.transfer((color >> 5) & 0x3F); //G color   SPI.transfer(color & 0x1F); //B color   delay(1);   digitalWrite(ss, HIGH); } //функция рисует прямоугольник заданной высоты ширины и цвета, левый верхний угол прямоугольника задается первыми двумя аргументами void oledRect (uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t colorFrame) {   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0x26); //настройка заливки прямоугольника   SPI.transfer(0x0); //отключаем заливку прямоугольника   SPI.transfer(0x22);   SPI.transfer(x); //x start   SPI.transfer(y); //Y start   SPI.transfer(x + w); //X end   SPI.transfer(y + h); //Y end   delay(1);   SPI.transfer((colorFrame >> 11) & 0x1F); //R color frame   SPI.transfer((colorFrame >> 5) & 0x3F); //G color   SPI.transfer(colorFrame & 0x1F); //B color   delay(10);   digitalWrite(ss, HIGH); } //то же самое, но прямоугольникк залит определенным цветом (6 аргумент задает цвет заливки) void oledRectFill (uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t colorFrame, uint16_t colorFill) {   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0x26); //настройка заливки прямоугольника   SPI.transfer(0x1);  //включаем заливку прямоугольника   SPI.transfer(0x22);   SPI.transfer(x); //x start   SPI.transfer(y); //Y start   SPI.transfer(x + w); //X end   SPI.transfer(y + h); //Y end   delay(1);   SPI.transfer((colorFrame >> 11) & 0x1F); //R color frame   SPI.transfer((colorFrame >> 5) & 0x3F); //G color   SPI.transfer(colorFrame & 0x1F); //B color   SPI.transfer((colorFill >> 11) & 0x1F); //R color fill   SPI.transfer((colorFill >> 5) & 0x3F); //G color   SPI.transfer(colorFill & 0x1F); //B color   delay(10);   digitalWrite(ss, HIGH); } Так же предусмотрена функция очистки прямоугольной области дисплея и она же используется для очистки всего дисплея.
      void oledClear(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) {   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0x25);   SPI.transfer(x1);   SPI.transfer(y1);   SPI.transfer(x2);   SPI.transfer(y2);   delay(1);   digitalWrite(ss, HIGH); } void oledClearAll() {   oledClear(0, 0, 95, 63); } И ещё команды скролинга дисплея. В них я глубоко не вникал, заставил картинку двигаться вертикально, но не смог заставить двигаться горизонтально. На том и хватит, я вряд ли буду использовать эти команды.
       
      //настройка скролинга дисплея void oledScrollSetup (uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint8_t e) {   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0x27);   SPI.transfer(a);   SPI.transfer(b);   SPI.transfer(c);   SPI.transfer(d);   SPI.transfer(e);   delay(1);   digitalWrite(ss, HIGH); } void oledScrollOn() {   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0x2F);   digitalWrite(ss, HIGH); } void oledScrollOff() {   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0x2E);   digitalWrite(ss, HIGH); } Приведу весь код "скетча".
      #include <SPI.h> const int ss = 10; //slave select const int dc = 8; // data/command data=1 command=0 const int reset = 9; //oled reset=0 void oledCommand(uint8_t val) //общая функция отправки команды дисплею {   digitalWrite(ss, LOW); //slave select устанавливаем в 0, это активирует SPI   digitalWrite(dc, LOW); //DC равен 0, это значит что отправляется команда   SPI.transfer(val); //отправляем команду стандартной функцией библиотеки SPI   digitalWrite(ss, HIGH); //slave select устанавливаем в 1, это означает что работа с SPI завершена } void oledData(uint8_t val) //общая функция отправки данных дисплею {   digitalWrite(ss, LOW); //slave select устанавливаем в 0, это активирует SPI   digitalWrite(dc, HIGH); //DC равен 1, это значит что отправляются данные   SPI.transfer(val); //отправляем данные стандартной функцией библиотеки SPI   digitalWrite(ss, HIGH); //slave select устанавливаем в 1, это означает что работа с SPI завершена } void oledDataColor(uint16_t color) //измененная функция для отправки 16-битного значения цвета {   digitalWrite(ss, LOW);   digitalWrite(dc, HIGH);   SPI.transfer(color >> 8); //разбиваем 16-битное значение на 2 8-битных   SPI.transfer(color);   digitalWrite(ss, HIGH); } void oledInit() //функция инициализации дисплея {   digitalWrite(reset, HIGH); //процедура сброса дисплея   delay(100);   digitalWrite(reset, LOW);   delay(100);   digitalWrite(reset, HIGH);   delay(100);   //процедура инициализации дисплея   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0xAE); //display OFF   SPI.transfer(0xA0); //remap & color depth setting   SPI.transfer(0x72);          //b01110010 расшифровка ниже   /*   b01 - 65k format, (00 -256 color, 10 - 65k color format 2)   1 - enable COM split odd even (0 - disable)   1 - scan COM95 to COM0 (0 - COM0 to COM95) отражение по короткой стороне   0 - disable left-right swaping (1 - enable swaping)   0 - RGB color (1 - BGR color)   1 - RAM column 0 to 95 (0 - 95 to 0)   0 - horizontal address increment (1 - vertical)   */   SPI.transfer(0xA1); //set display start line (0-63)   SPI.transfer(0x0);   SPI.transfer(0xA2); //set vertical offset (0-63)   SPI.transfer(0x0);   SPI.transfer(0xA4); //normal display (A5 - all pixel ON, A6 - all pixel OFF, A7 - inverse display)   SPI.transfer(0xA8); //set MUX ratio N+1 mux   SPI.transfer(0x3F); //default 0x3F   SPI.transfer(0xAD); //select internal Vcc supply   SPI.transfer(0x8E); //default 0x8E   SPI.transfer(0xB0); //set power saving mode   SPI.transfer(0x0B); //default 0x0B (disable power saving mode) 0X1A - enable   SPI.transfer(0xB1); //set reset, pre-charge period   SPI.transfer(0x31); //default 0x31   SPI.transfer(0xB3); //oscillator frequency   SPI.transfer(0xF0); //default 0xF0   SPI.transfer(0x8A); //set second pre-charge color A   SPI.transfer(0x64); //default 0x64   SPI.transfer(0x8B); //set second pre-charge color B   SPI.transfer(0x78); //default 0x78   SPI.transfer(0x8C); //set second pre-charge color C   SPI.transfer(0x64); //default 0x64   SPI.transfer(0xBB); //set pre-charge voltage level   SPI.transfer(0x3A); //default 0x3A   SPI.transfer(0xBE); //set COM deselect voltage level   SPI.transfer(0x3E); //default 0x3E   SPI.transfer(0x87); //set master current   SPI.transfer(0x06); //default 0x06   SPI.transfer(0x81); //set contrast for color A   SPI.transfer(0x91); //default 0x91   SPI.transfer(0x82); //set contrast for color B   SPI.transfer(0x50); //default 0x50   SPI.transfer(0x83); //set contrast for color C   SPI.transfer(0x7D); //default 0x7D   SPI.transfer(0xAF); //display ON, normal mode   digitalWrite(ss, HIGH); } uint16_t color565(uint8_t r, uint8_t g, uint8_t b) //функция преобразования цвета R8G8B8bit в формат R5G6B5bit {   uint16_t c;   c = r >> 3;   c <<= 6;   c |= g >> 2;   c <<= 5;   c |= b >> 3;   return c;// получаем 16-битное значение цвета и возвращаем его } //функция задает цвет выбранной точке void oledPixel(uint8_t x, uint8_t y, uint16_t color) {   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0x15);   SPI.transfer(x);   SPI.transfer(95);   SPI.transfer(0x75);   SPI.transfer(y);   SPI.transfer(63);   delay(1);   digitalWrite(dc, HIGH);   SPI.transfer(color >> 8);   SPI.transfer(color);   delay(1);   digitalWrite(ss, HIGH); } void oledSetArea(uint8_t x, uint8_t y, uint8_t w, uint8_t h) {   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0x15);   SPI.transfer(x);   SPI.transfer(y);   SPI.transfer(0x75);   SPI.transfer(x + w);   SPI.transfer(y + h);   delay(1);   digitalWrite(ss, HIGH); } //функция отрисовывает линию определенного цвета между двумя указанными координатами void oledLine (uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t color) {   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0x21);   SPI.transfer(x1); //x start   SPI.transfer(y1); //Y start   SPI.transfer(x2); //X end   SPI.transfer(y2); //Y end   delay(1);   //здесь синтезированный в формат 565 цвет разбирается отбратно   //я понимаю что это костыль, но во первых для задания цвета необходимо использовать один аргумент вместо трех   //а во вторых, я использовал именно такой способ для общего понимания работы с цветом при работе с данным дисплеем   SPI.transfer((color >> 11) & 0x1F); //R color   SPI.transfer((color >> 5) & 0x3F); //G color   SPI.transfer(color & 0x1F); //B color   delay(1);   digitalWrite(ss, HIGH); } //функция рисует прямоугольник заданной высоты ширины и цвета, левый верхний угол прямоугольника задается первыми двумя аргументами void oledRect (uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t colorFrame) {   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0x26); //настройка заливки прямоугольника   SPI.transfer(0x0); //отключаем заливку прямоугольника   SPI.transfer(0x22);   SPI.transfer(x); //x start   SPI.transfer(y); //Y start   SPI.transfer(x + w); //X end   SPI.transfer(y + h); //Y end   delay(1);   SPI.transfer((colorFrame >> 11) & 0x1F); //R color frame   SPI.transfer((colorFrame >> 5) & 0x3F); //G color   SPI.transfer(colorFrame & 0x1F); //B color   delay(10);   digitalWrite(ss, HIGH); } //то же самое, но прямоугольникк залит определенным цветом (6 аргумент задает цвет заливки) void oledRectFill (uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t colorFrame, uint16_t colorFill) {   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0x26); //настройка заливки прямоугольника   SPI.transfer(0x1);  //включаем заливку прямоугольника   SPI.transfer(0x22);   SPI.transfer(x); //x start   SPI.transfer(y); //Y start   SPI.transfer(x + w); //X end   SPI.transfer(y + h); //Y end   delay(1);   SPI.transfer((colorFrame >> 11) & 0x1F); //R color frame   SPI.transfer((colorFrame >> 5) & 0x3F); //G color   SPI.transfer(colorFrame & 0x1F); //B color   SPI.transfer((colorFill >> 11) & 0x1F); //R color fill   SPI.transfer((colorFill >> 5) & 0x3F); //G color   SPI.transfer(colorFill & 0x1F); //B color   delay(10);   digitalWrite(ss, HIGH); } void oledClear(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) {   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0x25);   SPI.transfer(x1);   SPI.transfer(y1);   SPI.transfer(x2);   SPI.transfer(y2);   delay(1);   digitalWrite(ss, HIGH); } void oledClearAll() {   oledClear(0, 0, 95, 63); } //настройка скролинга дисплея void oledScrollSetup (uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint8_t e) {   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0x27);   SPI.transfer(a);   SPI.transfer(b);   SPI.transfer(c);   SPI.transfer(d);   SPI.transfer(e);   delay(1);   digitalWrite(ss, HIGH); } void oledScrollOn() {   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0x2F);   digitalWrite(ss, HIGH); } void oledScrollOff() {   digitalWrite(ss, LOW);   digitalWrite(dc, LOW);   SPI.transfer(0x2E);   digitalWrite(ss, HIGH); } void setup() {   pinMode(ss, OUTPUT);   pinMode(dc, OUTPUT);   pinMode(reset, OUTPUT);   SPI.begin();   SPI.setDataMode(SPI_MODE3);   oledInit();   oledClearAll();   randomSeed(millis); } void loop() {  oledClearAll();   oledPixel(10, 10, color565(255, 0, 0));   oledLine(45, 32, 40, 63, color565(0, 255, 0));   oledRectFill(60, 0, 10, 20, color565(0, 0, 255), color565(255, 255, 0));   oledRect(40, 0, 10, 20, color565(255, 255, 0));   int x = 20, y = 31, w = 10, h = 10;   oledSetArea(x, y, w, h);   for (int i = 0; i < (w*h); i++) {     oledDataColor(color565(random(0, 255), random(0, 255), random(0, 255)));   }      delay(5000); } Результат работы на фото (специально сдвинул экспозицию в минус): вывод точки, линии, залитого и пустого прямоугольника и массива из точек случайного цвета.

      Плюсы данного дисплея очевидны: малое потребление из-за отсутствия подсветки, малая толщина дисплея, большие углы обзора, ну и наконец он цветной. Чип SSD1331 позволяет обращаться к каждой точке напрямую ( в отличии от монохромного дисплея на чипе SSD1306), что намного упрощает работу с ним. Ну и библиотеки для этого дисплея уже написаны, а то я тут всё велосипеды изобретаю.
      P.S. В архиве скетч, библиотеки для ArduinoIDE и даташиты.
      SSD1331.rar
    • Автор: CasperReduct
      Заранее извиняюсь если вопрос для многих будет примитивным, но так как в радиотехнике 0  - прошу помощи.
      Итак: есть Arduino mini,  различные датчики, датчик MQ135(потребление ~150mA). Питание: к пинам +5,Gnd припаян Microusb для подключения зарядника от телефона (но также хочу дать возможность запитать от 3 батареек).
      вопрос:
      1. как сделать обвязку чтобы при подключении внешнего источника питания, питание от батареек не тратилось?
      2. MQ135 пишут везде нужно свое питание но если я запитаю от внешнего источника его и ардуино то никаких проблем не возникнет?
      3. надо датчик MQ135 включать периодически допустим раз в 10мин на 2 мин c помощю ардуино, какие элементы могут помочь в этом?(использовать реле мне кажеться как с ружья по воробьям) 
    • Автор: jams
      Привет всем. первый раз держу ардуинку. Поставили такую задачу: На руки дали Arduino Mega 2560 R3   и такую задачу. надо задействовать 8 входов, а остальное выходы оставшиеся (их там много). Надо сделать так что бы эти 8 входов были расширены таким способом.: Допустим на  вход 1 подаем единичку а на другом выходе тоже единичка и так до восьми входов., но далее мы подаем комбинацию вход 1 и 2 вместе подаем по единичке и единичка выходит еще на одном свободном выходе и так со всеми восемью входами. например имеем входы 1,2,3,4,5,6,7,8, и делаем такую комбинацию после того как все выходы исчерпаны по одиночному подключению вход и выход. продолжаем дальше вход1+2=выход9 и так далее: 1+3=10, 1+4=11, 1+5=12... потом 2+2=...2+3...2+4... и так далее пока не закончатся все выходы. Теперь вопрос от человека первый раз державшего на руках вышеописанный девайс: Как это нарисовать в скетче? 
      БлагоДарю!