Автосэмплер — жизнь после жизни

в 11:45, , рубрики: arduino, autosampler, ctc, PAL, Разработка робототехники, робототехника

Жил он долго и счастливо… а потом сломался.

Пролог

Году, кажется в 2009 для одного проекта был куплен прибор-анализатор воды. Ввиду того, что предполагалось его использовать для обеспечения работы технологического оборудования, прибор был куплен в комплектации с автосэмплером.

Автосэмплер — жизнь после жизни - 1

Это по сути ЧПУ-манипулятор для автоматической подачи образцов в анализатор с четырьмя степенями свободы перемещений.

Отработал он около 10 лет и подал более тридцати тысяч образцов с некоторыми незначительными неприятностями, которые, впрочем, преодолевались «малой кровью».

В начале сего года он устал — отказала ось Z, вертикального перемещения.

То есть менипулятор просто перестал «видеть» её. В виду ряда обстоятельств официального обслуживания у измерительного комплекса не было никогда и мелкие проблемы (ремонт БП, перепрошивка после сбоя FLASH) решались самостоятельно. Тут же пришлось искать официалов, от которых выяснились… Некоторые особенности:

  • оказалось, что манипулятор не просто стар, а катастрофически стар
  • он был стар и снят с производства уже при его покупке
  • менять надо всю электронику
  • запчасти доступны, но стоят дороже нового
  • стопроцентной гарантии, что с заменой он заработает нет

Некоторые особенности, которые мне были известны:

  • прошивка изготовителя с анализатором не работает (хорошо, что был сделан бэкап),
  • видимо изменен также загрузчик прошивки, так как заводская прошивка «как есть » не принимается
  • возможности «перепрошить» загрузчик нет, так что покупать электронику за 6 k$ бесполезно
  • механика в отличном состоянии, так как я ее периодически обслуживал
  • датчики нулей (Холла) живы

Таким образом получилось два варианта:

  • покупка нового у производителя анализатора за 17k$ и непонятный срок поставки
  • переделка всей электроники и написание программ

Часть первая, хардверная

Для начала я решил убедиться в работоспособности механики при напряжении питания 12в (против 37 в оригинале). Понизить решил из-за того, что силовые полумосты управления ШД приводов прилично грелись. Потому были вытащены из тумбочки драйвера А4988, CNC шильд и Arduino NANO. все это было состыковано, прошито известным проектом grbl и с пристрастием допрошено. Были получены максимальные частоты хода ШД для каждого привода, коэффициенты деления шага, отрегулированы токи драйверов.

Оказалось, что XY вообще не греются, причем выдают вполне подходящую скорость. Ток для привода Z — пришлось вкручивать на максимум, по причине деления на 8 и приличного потребления при начале движения вверх, так как оно тянет нехилую массу из двух ШД и требухи, при этом микросхема драйвера грелась градусов до 50 даже с радиатором. Пришлось в конечной конструкции добавлять кулер на вдув напротив этого привода.

В итоге вместо этого

Автосэмплер — жизнь после жизни - 2

получилось это

Автосэмплер — жизнь после жизни - 3

Про Arduino MICRO будет отдельная песнь. На заднем плане панель с тумблерами выбора режима работы, кнопками пуск и ресет.

Теперь про требуху. как я говорил все датчики Холла выжили. Из них XY неинтересно, но например вот X.

Про Z отдельная песня. Там, в корпусе Z еще живет привод плунжера шприца, без датчика нуля, но со сдвоенным датчиком вращения — практически энкодер. А еще там есть датчик нажатия на виалу с пробой, реализованный винтовой передачей и также датчиком Холла. Эти оба датчика вращения представляют собой латунные шестерни, проходящие зубьями мим датчиков Холла с подмагничиванием.

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

В итоге вместо этого

Автосэмплер — жизнь после жизни - 4

получилось это

Автосэмплер — жизнь после жизни - 5

Часть вторая, софтверная

Испытания на CNC шильде показали приличну скорость. НО! Если Вы попытаетесь предложить ШД сразу частоту STEP, соответствующую этой скорости, то кроме рычания на месте ничего не получите. Для выхода на приличные скорости перемещений ШД необходимо разгонять, равно как, если Вам дороги шестерни и рейки привода (ну или ШВП, или ремни) то и замедлять ПЛАВНО.
потому в общем тривиальный код несколько разросся.

Поскольку приходить в раздел «Робототехника» со статьёй без кода почти неприлично, вот к примеру управление привода Z (для порицания). При выдаче частоты на STEP digitalWrite не успевает, приходится дергать портом напрямую. Задержки наверно можно было и delay, но код пришел из управления по XY, а там нужна одновременность.

//***************** ПЕРЕМЕЩЕНИЕ Z *************************
void movement_z (unsigned int  tz, int spd) {
long interval_z;
long spd_z  = 2000;
unsigned long cur_micros;
unsigned long prev_micros_z =0;
int half_z;
byte full_mask = mask_z;

int dz = tz - z;  
z=z+dz; 
if (dz <0) digitalWrite(pin_dir_z, HIGH); else digitalWrite(pin_dir_z, LOW);
dz = abs(dz);

half_z = int(dz/2);
interval_z = spd;

do {
if (dz>0){
cur_micros = micros();
if(cur_micros - prev_micros_z > spd_z) {
  if ( dz>half_z ) 
      {if (spd_z > interval_z) {spd_z = spd_z - 5;} else  spd_z = interval_z;}
  if ( dz<300 ) 
      {if (spd_z < 1000) spd_z = spd_z + 2; else  spd_z = 3000;}

  prev_micros_z = cur_micros; 
  if (dz>0) {PORTB =  PORTB | mask_z; dz--;}
}}
   delayMicroseconds(5);
    PORTB =  PORTB & B11110000;
   } while( dz != 0);
}
//*************************************************************

В наборе функции уровней:

  • низкого — поехать туда-сюда, найти то-незнаю-что
  • среднего — откалиброваться в нули, набрать шприц, сделать закол образца
  • высокого — циклограмма обхода n-го количества виал на палетте

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

Главная циклограмма выглядит так:

inline void frame_1(){
for (unsigned int i=0; i<6; i++){                                                                        // 6
for (unsigned int j=0; j<9; j++){                                                                        // 9

for (unsigned int k=1; k < probe+1; k++){
for (unsigned int l=1; l < inj+1;   l++){
   sound1();
   delay(1000);
   if (inj == 2) {tone(tone_p,5000);delay(200);noTone(tone_p);delay(200);tone(tone_p,5000);delay(200);noTone(tone_p);}    
   if (inj == 1) {tone(tone_p,5000);delay(200);noTone(tone_p);}

Serial.print("going to x = ");Serial.print(j+1);Serial.print(" y = ");Serial.print(i+1); Serial.print(" probe = ");Serial.print(k); Serial.print(" inj = ");Serial.println(l);
   show_xyzp();  
   movement_z (0,450);
   movement_xy (prime_x-j*272, prime_y+i*372,500);
   movement_z(1800,300); 
   if (z>2500) ost();
   fill();
  while(sensor());
   if (inj == 1) {click_mouse();
                  Serial.println("mouse CLICKED for FLUSH and inj=1");}
   if (inj == 2  && l==1) {click_mouse();
                  Serial.println("mouse CLICKED for FLUSH and inj=2");}
 
   septa_pos();
   while(sensor());   
   sound2();
   inject();
   }
   delay(3000);
   click_mouse();
   Serial.println("mouse CLICKED for INJECT");
   find_zero_xy();
    movement_xy (3257, 1247,500);
    movement_z (6000,100);    
    movement_z (0,100);      
   
}
}
}
}

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

Автосэмплер — жизнь после жизни - 6

Главная проблема составления программы заключалась в том, что в оригинале анализатор выдаёт автосэмплеру куда ехать и что делать. Все это происходдит по COM-порту и по протоколу, который взять неоткуда. Потому пришлось выкручиваться.

У анализатора есть ручной режим для тех кто не купил белку автосэмплер. При этом на экране анализатора возникает темная кнопка «sample ready» и когда сделан закол оператор должен ткнуть в неё мышью (трекером на панели анализатора). Когда измерение завершено возникает темная кнопка «start flushing» и, если у оператора есть еще один образец он нажимает ее мышбю, для подготовки анализатора к следующему измерению.

К счастью у анализатора оказался порт USB и достаточно необрезанный RedHat розлива начала 2000, чтобы цеплять воткнутое в этот порт автоматически Именно для эмуляции мышы на новой главной плате автосэмплера стоит Arduino MICRO. она получает PINок от NANO в момент, когда анализатор необходимо кликнуть. Писать перемещение было лень, потому перед началом работы мышь надо выставить на кнопку заранее.

О СЧАСТИЕ, что отягощенный опытом, я развязал мышиную часть от прочей управленческой гальванически, копеечным оптроном. ИБО к концу второго дня отладки на натуре, когда всё уже совсем работало и я настраивал биппер для подачи звуков, похожих на оригинальные один из драйверов выпустил волшебный дым и соединил 12в силовой части и 5в логической. Ну ничего, под дня замены на извлечённое из бездонной тумбочки это не ремонт анализатора за 100к$. Правда потом оказалось, что купленный взамен забытого дома новый БП REXANT в какой-то момент стал выдавать вместо 12в почти 50, что и вызвало досадную задержку.

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

Автосэмплер — жизнь после жизни - 7

Эпилог

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

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

Автор: solderman

Источник

Поделиться

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js