Поворотный стол для 3д сканирования .

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

 

Добрый день .
Занимался темой **DAVID 3 ** в 2014 году. Собрал вполне рабочую конструкцию .
Не давно установил **DAVID 4 ** и очень мне понравилась функция поворотного стола .Стол у меня был сделан уже давно но управляется кнопкой .

Изображение

Изображение

Стол может быть зафиксирован в любом положении в 3 осях , спокойно поворачивать вес до 3 кг .
Очень хотелось бы автоматизировать весь процесс .Полазил по инету нашел вот такой вариант .

https://sites.google.com/site/janbeck/3 ... for-david4 

Автор пишет что все работает .Но автор полез на шину i2C .Он управляет шаговым мотором .В моём варианте стоит концевик на поворотном столе на 12 секторов .Концевик запараллелен с кнопкой . 

КОД: ВЫДЕЛИТЬ ВСЁ • РАЗВЕРНУТЬ
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"
// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// Connect a stepper motor with 400 steps per revolution (0.9 degree)
// to motor port #2 (M3 and M4)
Adafruit_StepperMotor *myMotor = AFMS.getStepper(400, 2);
void setup() {
  Serial.begin(9600);   // open serial port
  AFMS.begin();         // create with the default frequency 1.6KHz
  myMotor->setSpeed(1); // 1 rpm  
  myMotor->step(1, FORWARD, MICROSTEP);  // take a step to initialize position
  delay(250);           // settle mechanics for 250 ms
  myMotor->release();   // turn off current
}
void loop() {
  static int counter = 0;
  if(Serial.available()>0) // is there any unread serial data?
    {
    char ch = Serial.read();    // read a character from the serial port
    Serial.print("echo");Serial.println(ch); // echo back so that it is displayed in DAVID debug console
    if (ch == '2')              // is it the character for the number 2?
      {
      counter = counter + 1;    // increment the scan count
      myMotor->step(10, FORWARD, MICROSTEP); // take a step
      delay(250);           // settle mechanics for 250 ms
      myMotor->release();   // turn off current
      if (counter == 40)    // we have performed a full rotation
        {
          counter = 0;      // reset for next scan
        }
      else
        {
        Serial.println("S"); // Tell DAVID to do another Scan
        }
      }
    }  // end Serial.available
  }

Может кто посмотрит из знающих и отзывчивых .Как бы его переделать под такой алгоритм работы .

1 .При нажатии (сканировать )*стол неподвижен .

2 .По окончание сканирования ( примерно 30 сек )

*должна пройти команда на включение реле (для наглядности пин 13)

примерно 7 секунд и отключится .(концевик должен замкнуться )

3 .Через 20 сек.( время для поворота на сектор )*должна пройти команда (" S ") сканировать .

4 .Далее по циклу 12 раз .(стол разбит на 12 секторов ) Каждое включение поворачивает стол на 30 градусов .

Опыта в программирование нет .Только в готовых скетчах что нибудь подправить под свои нужды .
Если можно помогите пожалуйста .

Сканирование происходит в темноте .Свет от проектора очень резкий .Сильно устают глаза .Если удалось бы автоматизировать было бы замечательно .

 

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019
Попробовал сам составить скетч .По образу и подобию .

Взял типовую схему включение реле для ардуино .Отключил концевик .

Навешал что мог .Работает . 





В момент включения ардуино стол крутиться .

При команде "S" через монитор включается таймер и стол вращается 22 сек. Останавливается и проходит команда "S" .Через 40 сек.включается стол и так до бесконечности .

Хотелось бы чтобы после прохождение 12 циклов .Останавливалось и подавало сигнал зуммер например .




КОД: ВЫДЕЛИТЬ ВСЁ • РАЗВЕРНУТЬ
const int relPin = 13;

void setup() {
  Serial.begin(9600);   // open serial port
    pinMode(relPin, OUTPUT);
}

void loop() {
    static int counter = 0;
  if(Serial.available()>0) // is there any unread serial data?
    digitalWrite(relPin, HIGH);
    delay(40000);// время сканирования
    digitalWrite(relPin, LOW);
    delay(22000);//поворот стола 
     if (counter == 180)    // we have performed a full rotation
        {
   
          counter = 0;      // reset for next scan
        }
      else
        {
        Serial.println("S"); // Tell DAVID to do another Scan
        }
    }





Кривенько но как смог . DAVID приблуду видит и команда "S" проходит .

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

Неудача — это только повод начать заново, на сей раз умнее.

 
sadman41
Offline
Зарегистрирован: 19.10.2016

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

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

Я и пишу как смог .Собрал методом вставки из 2 скетчей .Но как не странно работает .

Помогите пожалуйста сделать цикличность 12 раз .

sadman41
Offline
Зарегистрирован: 19.10.2016

Работает, но не так, как Вам надо. Значит не очень правильно работает.

Помочь можно, но концепцию менять надо полностью. Встраиваться во все эти delay() у меня никакого интереса нет. 

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

Готов принять ваше решение .Если есть более итересное и правильное  .

fogary
Offline
Зарегистрирован: 05.03.2016

DIFO пишет:

...

void loop() {
    static int counter = 0;
  if(Serial.available()>0) // is there any unread serial data?
    digitalWrite(relPin, HIGH);
    delay(40000);// время сканирования
    digitalWrite(relPin, LOW);
    delay(22000);//поворот стола 
     if (counter == 180)    // we have performed a full rotation
        {
             counter = 0;      // reset for next scan
        }
      else
        {
        Serial.println("S"); // Tell DAVID to do another Scan
        }
    }

Лихо Вы шашкой рубанули изначальный код.

В исходном коде процесс запускался, если в порт приходила команда "2". У вас осталась только проверка, что в порт что-то пришло (не важно что). В исходном варианте, все дальнейшие действия зависили от этого условия, т. е. были заключены в фигурные скобки. У Вас же, от этой проверки зависит только одна команда: "digitalWrite(relPin, HIGH);", все остально выполняется в любом случае. В исходном варианте, подсчитывалось кол-во включений-выключений шагового двигателя. У Вас видимо реализовано как-то по другому, и значение счетчика не меняется.

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

Да уж погарячился .
Стол сделан просто двигатель и мощный редуктор .
Работает много лет .
Захотелось автоматизировать процесс .
Помогите пожалуйста сделать правильно .

fogary
Offline
Зарегистрирован: 05.03.2016

Для начала, давайте проясним.

В начальном коде, после получения в порт символа "2", шаговый двигатель поворачивает стол на некий угол. Если, после этого поворота стол не вернулся в исходную позицию (совершил полный оборот), в порт выводится символ "S".
Что или кто подает команду "2"? Команда "S" - запускает сканирование?

В Вашем коде, 22 с - это поворот на угол или полный оборот?
Вы хотите что бы процесс останавливался после 12 циклов. 12 циклов чего - поворотов на угол или полных оборотов?
В каком порядке выполняются действия: сначало сканирование, потом поворот стола или наоботрот?

fogary
Offline
Зарегистрирован: 05.03.2016

Как вариант (по мотивам исходного кода). 12 циклов "поворот->сканирование" и останов:

const int relPin = 13;

void setup() {
  Serial.begin(9600);
  pinMode(relPin, OUTPUT);
  digitalWrite(relPin, HIGH); //установить начальное состояние реле - выключено (?)
}

void loop() {
  static boolean do_scan = TRUE; //можно сканировать
  static int counter = 0;
  
  if (do_scan) {
    digitalWrite(relPin, LOW); //включить реле (?)
    delay(22000); //время поворота
    digitalWrite(relPin, HIGH); //выключить реле (?)

    counter++; 

    if (counter == 12) {
      counter = 0; //обнулить счетчик
      do_scan = FALSE; //хватит сканировать
      //
      // тут могла быть команда(ы) для подачи звукового сигнала
      //
    } else {
      Serial.println("S"); //подать команду на сканирование
      delay(40000); //время сканирования
    }
  }
}

 

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

Задача программы .
Повернуть стол на определенный угол .Мотор не шаговый поэтому им можно управлять только по времени .Ставить датчики не вариант .Управляя временем работы легко перестроить на другой угол поворота .
После поворота на 30 градусов (22секунды) программа должна отправить в DAVID команду на сканирование . Время сканирования также проще задать таймером ( 40секунд ).
И так 12 раз.
Ну и вишенка на торте .Сигнал зуммера .

fogary
Offline
Зарегистрирован: 05.03.2016

Выше привел вариант.

Так понимаю, сейчас каждое сканирование запускается после перезагрузки Arduino? Не думали, вместо этого, запускать сканирование нажатием кнопки?

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019
 
Сейчас я его загружу .
Наверно было бы проще кнопкой .
 
 
DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019
,
 
DAVID_12:11: error: 'TRUE' was not declared in this scope
 
   static boolean do_scan = TRUE; //можно сканировать
 
                            ^
 
DAVID_12:23: error: 'FALSE' was not declared in this scope
 
       do_scan = FALSE; //
 
              
'TRUE' was not declared in this scope
 
Ругается при загрузке .
 
sadman41
Offline
Зарегистрирован: 19.10.2016

значения true и false в нижнем регистре должны быть написаны.

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019
[code]
const int relPin = 13;


void setup() {

  Serial.begin(9600);

  pinMode(relPin, OUTPUT);

  digitalWrite(relPin, HIGH); //установить начальное состояние реле - выключено (?)

}
void loop() {

  static boolean do_scan = true; //можно сканировать

  static int counter = 0;

  if (do_scan) {

    digitalWrite(relPin, LOW); //включить реле (?)

    delay(22000); //время поворота

    digitalWrite(relPin, HIGH); //выключить реле (?)
    counter++;
    if (counter == 12) {

      counter = 0; //обнулить счетчик

      do_scan = false; //хватит сканировать

      //

      // тут могла быть команда(ы) для подачи звукового сигнала

      //

    } else {

      Serial.println("S"); //подать команду на сканирование

      delay(40000); //время сканирования

    }

  }

}
[/code]

Дошло не сразу  .Спасибо помогли ,все заработало . 

Программисты шутят .Хи Хи Хи.

fogary
Offline
Зарегистрирован: 05.03.2016

Извиняюсь за мой косяк с "TRUE" и "FALSE".

DIFO пишет:
Наверно было бы проще кнопкой.

Как подключать кнопку знаете?

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

 ""  Извиняюсь за мой косяк с "TRUE" и "FALSE".  "" Ерунда воспринял как тест на сообразительность .Не прошол .

Сегодня гонял  программу ВСЁ четко СПАСИБО .

Если не трудно допишите пожайлуста .

1.кнопку надо обязательно  (пришлось открывать монитор порта для запуска ) 

2.зуммер (есть активный ) окончания сканирования .(вишенка на торте )

nik182
Offline
Зарегистрирован: 04.05.2015

Ну а самому за строкой хватит сканировать поднять и опустить ногу с зумером на время делэя как хочется писка?

А кнопку простым циклом вайл пока не нажата держать на месте? На форуме полно примеров строки пока кнопка не нежата ничего не делать. 

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

Конечно попробовать можно .
Но могу наваротить такого , 2 ардуины уже загубил .Опасаюсь .

fogary
Offline
Зарегистрирован: 05.03.2016

Вариант с кнопкой.  Подключение:

(GND)—[ резистор 10 КОм ]—(buttonPin)—[ кнопка ]—(+5V)

const int relPin = 13;
const int buttonPin = 9;
const int zummerPin = 10;

boolean debounce(int pin);
void beep_beep();

void setup() {
  Serial.begin(9600);
  pinMode(relPin, OUTPUT);
  pinMode(zummerPin, OUTPUT);
  pinMode(buttonPin, INPUT);
  digitalWrite(relPin, HIGH);
}

void loop() {
  static boolean do_scan = false;
  static int counter = 0;

  if (debounce(buttonPin)) { //состояние нажатой кнопки = HIGH
    do_scan = true;
  }
  
  if (do_scan) {
    digitalWrite(relPin, LOW);
    delay(22000);
    digitalWrite(relPin, HIGH);

    counter++; 

    if (counter == 12) {
      counter = 0;
      do_scan = false;
      beep_beep(); 
    } else {
      Serial.println("S");
      delay(40000);
    }
  }
}

boolean debounce(int pin) {
  boolean previousState = digitalRead(pin);
  for(int counter = 0; counter < 10; counter++) {
    delay(1);
    boolean state = digitalRead(pin);
    if( state != previousState) {
      counter = 0;
      previousState = state;
    }
  }
  return state;
}

void beep_beep() {
  ; //тут будет пищалка
}

Номера контактов для кнопки и пищалки указаны только для примера!

Функция для пищалки введена, но ничего не делает, т. к. реализация зависит от типа пищалки.

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019
Arduino: 1.8.9 (Windows 7), Плата:"Arduino/Genuino Uno"

C:\Users\ДИФО\Documents\Arduino\14_06_2019\14_06_2019.ino: In function 'boolean debounce(int)':

14_06_2019:52:10: error: 'state' was not declared in this scope

exit status 1
'state' was not declared in this scope

Этот отчёт будет иметь больше информации с
включенной опцией Файл -> Настройки ->
"Показать подробный вывод во время компиляции"

Опять ругается .

Есть активный зуммер .Его и повешу .

 

kostyamat
Offline
Зарегистрирован: 16.11.2017

DIFO пишет:

Есть активный зуммер .Его и повешу .

Откройте для себя встроенную функцию tone();

К примеру tone(pinForBuzzer, 4000, 500); сгенерит вам писк частотой 4000 и длинной 500 миллисекунл на ножке выделенной под буззер. При этом она не является блокирующей, то-есть пищать будет, а останавливать выполнение программы - нет.

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

Это правильный подход к пассивному зуммеру .
Для активного это не нужно .Пришло 5 вольт пищит .

fogary
Offline
Зарегистрирован: 05.03.2016

DIFO пишет:

Опять ругается .

И снова мой косяк - не проверил. Так не ругается:

boolean debounce(int pin) {
  boolean state;
  boolean previousState = digitalRead(pin);
  for(int counter = 0; counter < 10; counter++) {
    delay(1);
    state = digitalRead(pin);
    if( state != previousState) {
      counter = 0;
      previousState = state;
    }
  }
  return state;
}

 

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

Fogari большое спасибо за вашу помощь .
Вечером попробую .

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

Все работает ЧЁТКО .

Только одно но . Программа выдаёт только 11 комманд "" S "" .Наверно нужно поставить не 12 а 13 циклов .

Гдето 1 теряетса .

Но ЭТО все нюансы и просто настройка .

Еще раз хочу ВАС поблагодарить за оказанную помощь .  DIFO 

fogary
Offline
Зарегистрирован: 05.03.2016

DIFO пишет:

Гдето 1 теряетса .

Возможно следует поменять порядок действий:

...
  if (do_scan) {
    if (counter < 12) {
      Serial.println("S");
      delay(40000);
      digitalWrite(relPin, LOW);
      delay(22000);
      digitalWrite(relPin, HIGH);
      counter++; 
    } else {
      beep_beep(); 
      do_scan = false;
      counter = 0;
    }
  }
...

 

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

Вечерком попробую .

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

Засунул все в корпус .Работает .
Только одно но .При подключение к usb компа реле несколько раз срабатывает и движок дёргается . Через пару секунд успокаивается и смирно ждёт нажатия кнопки . Это не критично но если можно исправить помогите пожалуйста .

sadman41
Offline
Зарегистрирован: 19.10.2016

Реле на D13 не вешайте.

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

Можно на любую другую .

На что это повлияет ?

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Возьмите Arduino, залейте туда пустой скетч. Отключите от USB, подключите от USB. Мигает LED на плате сразу после подключения?

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

Под рукой нет но завтра перезалью скетч с другой номерацией .

Неужели так просто ? Ведь 13 это обычный вывод + светодиод .ИЛИ всё сложнее .

nik182
Offline
Зарегистрирован: 04.05.2015

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

sadman41
Offline
Зарегистрирован: 19.10.2016

С резистором, конечно, правильный совет, но основная проблема в ином.

Для штатных бутлодеров. 

The only differences is the time the bootloader waits for a new program to arrive and the number of times it flashes the pin 13 LED when it starts. Because of the automatic reset on the Diecimila, its bootloader needs only wait a very short amount of time (less than a second) - to save time, it also flashes the pin 13 LED only once. The NG bootloader waits about 6-8 seconds and flashes the LED three times.

Для оптибута:

  1. On reset, Optiboot starts and reads the reset reason from MCUSR. For any cause other than "external reset", the application is started immediately. Otherwise, optiboot attempts to download new application software:
  2. The "start LED" is flashed to indicate that optiboot is running. (which pin is used, and how many times it flashes, is configurable.)
DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

Переписал с 13 на 12 и всё стало отлично работать . Теперь выдает 12 циклов и очень точно делает 360 градусов .Все работает как и задумано .

 

Спасибо ВСЕМ  за оказанную помощь .     DIFO .

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

Доброго дня .

Как известно аппетит приходит во время еды .

Эксплуатация стола ( ВСЕ ОТЛИЧНО РАБОТАЕТ ) выевила несколько моментов .

1 При изменение ула поворота приходится загружать скетч с измененными настроиками .

Можно ли добавить кнопку и менять время работы двигателя без перезагрузки .

2 Можно ли приспособить этот стол и для фото сьемки . Вместо (S) отправлять ИК код на фотоаппарат .

 

b707
Offline
Зарегистрирован: 26.05.2017

DIFO пишет:

Можно ли добавить кнопку и менять время работы двигателя без перезагрузки .

2 Можно ли приспособить этот стол и для фото сьемки . Вместо (S) отправлять ИК код на фотоаппарат .

 

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

но решать, конечно, исполнителю

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

А шо спросить нельзя  .  Помогать или нет ЭТО дело сугубо добровольное .

Последняя фраза ключевая .Только не ИСПОЛНИТЕЛЮ а неравнодушному форумчанину .

 P.S.        Давно очень давно обращаюсь за помощью на различные форумы но по поводу моей воспитанности первый раз получил подобный ответ .

 

 

b707
Offline
Зарегистрирован: 26.05.2017

DIFO пишет:

не ИСПОЛНИТЕЛЮ а неравнодушному форумчанину .

ну вот я и есть "неравнодушный форумчанин" - не могу пройти мимо, видя как вы fogari эксплуатируете. Он вам уже три варианта кода написал, а у вас каждый раз "все отлично, но есть одно но".

Вы бы хоть для приличия попытались что-то самостоятельно сделать, а то... Сказку о рыбаке и рыбке помните? Старуха в итоге осталась у разбитого корыта.

 

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

 

    На нет и спроса нет .

    

 

 

Onkel
Offline
Зарегистрирован: 22.02.2016

Я на диске для аэробики сделал
https://youtu.be/FFlwcblPyGo

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

У меня примерно тоже самое только компактней  и  работает в 3х осях .

С помощью FOGARI был добавлен автомат на ардуине и работать все стало намнаго приятней .

Подбери время работы двигателя и поворачивай на сколько нужно в автомате . Каждый раз дергать тумблер ЭТО не по феншую . Даже можно запитать все от USB .Надо подобрать резистор в цепь двигателя что бы ограничеть ток до 0,4 А . 

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

Облазил форумы но пока не как не подберу . Проще всего через "" remotexy  "" там все делается просто .Они сейчас даже добавили вариант через ОTG но проблемма в питании .

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

Onkel
Offline
Зарегистрирован: 22.02.2016

DIFO пишет:

  ограничеть ток до 0,4 А . 

 

Для этого отцы придумали ШИМ, а итальянцы 6 выходов ШИМ в ардуине сделали.

DIFO
DIFO аватар
Offline
Зарегистрирован: 09.06.2019

Шим это здорово . Только очень раздрожает этот писк , усложнение схемы .Зачем  он нужен , сдесь не требуется изменять скорость двигателя . Только время работы . Ограничев ток убираем лишний блок питания .Конечно если исползовать USB .Чем проще механизм тем дольше работает .