Датчик остановки/окончания филамента из “мыши”

kick_2
Идет загрузка
Загрузка
28.11.2016
15230
61
Техничка

Подпишитесь на автора

Подпишитесь на автора, если вам нравятся его публикации. Тогда вы будете получать уведомления о его новых статьях.

Отписаться от уведомлений вы всегда сможете в профиле автора.

40
Читая тему “И снова про датчик окончания филамента” и думая как можно её решить, я обратил внимание на “поведение” мыши – она то ярко светилась при движении, то тускло если её не трогать. Т.е. срабатывал переход в режим ожидания. Сразу возникли идеи и вопросы: будет ли сенсор мыши реагировать на филамент и можно будет отследить разницу в свечении. Опыт показал, мышь реагировала на движения филамента и засыпала при его остановке. Разобрав мышь, на светодиоде удалось измерить напряжение - 2.5В в активном состоянии и 1.7 в ожидании. Ура, датчику – БЫТЬ!

Но дальнейшая исследование показало, что без компьютера мышь не “загоралась”. Это удалось решить высоким уровнем на контакте D+. Но как оказалось, каждый раз режим перехода в ожидание и нахождение в нём был очень разный по времени и никак не удавалось разработать работающий алгоритм.

Поиск способа получения данных от мыши, привёл к нескольким ссылкам, где демонстрировалось получение координат перемещения мыши платой Arduino, но нужен был 'грызун' поддерживающий протокол обмена PS/2. Т.е. можно использовать для датчика не фантомное мигание, а реальное перемещение. Только теперь двигается уже не мышь, а филамент мимо сенсора. К сожалению мыши стандарта PS/2 поблизости не оказалось, но “интернет” подсказал, что обычно их делают универсальными 2-х стандартными PS/2 – USB. Мой подопытный образец A4TECH Model:X5-60MD хоть и имел разъем USB, но встречалось упоминание о продаже такой модели в двух видах. Я решил попробовать, и попытка оказалось успешной.

Теперь когда выяснилось, что моя мышь поддерживает протокол обмена PS/2. Из нескольких разных программ и библиотек работы с PS/2, мне удалось найти работающую с имеющейся в наличии контроллером: Deek-Robor Pro Micro на ATmega32u4, определяется как Arduino Leonardo. Мышь извлечена из корпуса и прикручена к распечатанной “направляющей”. Филамент свободно проходит в 2мм отверстие по центру сенсора на уровне “стола” т.е. 2,5 мм от сенсора.

В качестве алгоритма работы был реализован следующий порядок действий: если не было движения, т.е. считываются нулевые перемещения за последние 3 секунды и установлен высокий уровень на входе управления (G-code: M42 P4 S255), то подаётся высокий уровень на выход – 'звуковой сигнал'. Прототип работает с светодиодом, в дальнейшем в место светодиода, будет использоваться, выпаянная из модуля дисплея “пищалка”.

Т.е. если прозвучал звуковой сигнал, то желательно оперативно подойти к принтеру и возможно удастся исправить аварийную ситуацию, например: подтолкнуть пластик при образовании “проточки” или вставить новый при его окончании и т.п.

Саму схему распайки не привожу т.к. для реализации данной логики подойдёт практически любой Arduino-совместимый контроллер любой формы и размера, со своими номерами контактов. Для работы необходимо 3 цифровых выхода и 1 вход.

#define MDATA 6 – к контакту DATA PS/2 мыши.

#define MCLK 5 – к контакту CLK PS/2 мыши.

#define ledgnd 8 – можно не считать, лень было землю для светодиода тянуть.

#define led 7 – к контакту на индикацию/звук.

#define pinIn 9– вход признака необходимости сигнализации, к контакту D4 (и т.п.) SERVOS RAMPS 1.4.

Размер задержки (3 сек.) регулируется размером матрицы запоминаемых значений, через константу myzSize, сейчас проверка идёт 5 раз в сек (задержка в конце цикла 200 мсек.) и при 15 значениях будет ~3 сек. Для установки признака необходимости сигнализации, при остановке филамента, можно использовать любой pin Dx (D4,D5 …) на разъемах SERVOS, AUX-1 и AUX-2 на плате RAMPS 1.4. Ими можно управлять командами типа M42 P4 S255 и M42 P4 S0 и т.п. Которые вводятся из командной строки pronterface и т.п. программ или можно автоматически вставлять в G-code в момент его создания, например вкладка Custom G-code в Slic3R. Питание контроллера и мыши также можно организовать с контактов SERVOS RAMPS 1.4.

Несколько фото.

Площадка для крепления платы мыши и направляющая для филамента.
Датчик остановки/окончания филамента из “мыши”
В сборе.
Датчик остановки/окончания филамента из “мыши”
Со стороны платы мыши.
Датчик остановки/окончания филамента из “мыши”
Филамент не движется, загорелся светодиод.
Датчик остановки/окончания филамента из “мыши”
Вывод. Поставленная цель – сделать недорогой, но надёжный датчик остановки/окончания филамента из простой мыши, вполне осуществима.

Спасибо за внимание.

И, конечно, буду рад ответить на ваши вопросы, если таковые будут.

Тест программы. Взято на arduino.cc и творчески дополнено.

[CODE]/*

* an arduino sketch to interface with a ps/2 mouse.

* CLK(white) DATA(red) GND(green) 5V(blue)

* Also uses serial protocol to talk back to the host

* and report what it finds.

*/

/*

* USB-PS/2 - Pin 5 is the mouse D+ pin, pin 6 is the D- pin

*/

#define MDATA 6

#define MCLK 5

#define ledgnd 8

#define led 7

#define pinIn 9

#define myzSize 15

int myz[myzSize]= { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};

/*

* according to some code I saw, these functions will

* correctly set the mouse clock and data pins for

* various conditions.

*/

void gohi(int pin)

{

pinMode(pin, INPUT);

digitalWrite(pin, HIGH);

}

void golo(int pin)

{

pinMode(pin, OUTPUT);

digitalWrite(pin, LOW);

}

void mouse_write(char data)

{

char i;

char parity = 1;

// Serial.print('Sending ';);

// Serial.print(data, HEX);

// Serial.print(' to mouse

';);

// Serial.print('RTS';);

/* put pins in output mode */

gohi(MDATA);

gohi(MCLK);

delayMicroseconds(300);

golo(MCLK);

delayMicroseconds(300);

golo(MDATA);

delayMicroseconds(10);

/* start bit */

gohi(MCLK);

/* wait for mouse to take control of clock); */

while (digitalRead(MCLK) == HIGH)

;

/* clock is low, and we are clear to send data */

for (i=0; i < 8; i++) {

if (data & 0x01) {

gohi(MDATA);

}

else {

golo(MDATA);

}

/* wait for clock cycle */

while (digitalRead(MCLK) == LOW)

;

while (digitalRead(MCLK) == HIGH)

;

parity = parity ^ (data & 0x01);

data = data >> 1;

}

/* parity */

if (parity) {

gohi(MDATA);

}

else {

golo(MDATA);

}

while (digitalRead(MCLK) == LOW)

;

while (digitalRead(MCLK) == HIGH)

;

/* stop bit */

gohi(MDATA);

delayMicroseconds(50);

while (digitalRead(MCLK) == HIGH)

;

/* wait for mouse to switch modes */

while ((digitalRead(MCLK) == LOW) || (digitalRead(MDATA) == LOW))

;

/* put a hold on the incoming data. */

golo(MCLK);

// Serial.print('done.

';);

}

/*

* Get a byte of data from the mouse

*/

char mouse_read(void)

{

char data = 0x00;

int i;

char bit = 0x01;

// Serial.print('reading byte from mouse

';);

/* start the clock */

gohi(MCLK);

gohi(MDATA);

delayMicroseconds(50);

while (digitalRead(MCLK) == HIGH)

;

delayMicroseconds(5); /* not sure why */

while (digitalRead(MCLK) == LOW) /* eat start bit */

;

for (i=0; i < 8; i++) {

while (digitalRead(MCLK) == HIGH)

;

if (digitalRead(MDATA) == HIGH) {

data = data | bit;

}

while (digitalRead(MCLK) == LOW)

;

bit = bit << 1;

}

/* eat parity bit, which we ignore */

while (digitalRead(MCLK) == HIGH)

;

while (digitalRead(MCLK) == LOW)

;

/* eat stop bit */

while (digitalRead(MCLK) == HIGH)

;

while (digitalRead(MCLK) == LOW)

;

/* put a hold on the incoming data. */

golo(MCLK);

// Serial.print('Recvd data ';);

// Serial.print(data, HEX);

// Serial.print(' from mouse

';);

return data;

}

void mouse_init()

{

gohi(MCLK);

gohi(MDATA);

// Serial.print('Sending reset to mouse

';);

mouse_write(0xff);

mouse_read(); /* ack byte */

// Serial.print('Read ack byte1

';);

mouse_read(); /* blank */

mouse_read(); /* blank */

// Serial.print('Sending remote mode code

';);

mouse_write(0xf0); /* remote mode */

mouse_read(); /* ack */

// Serial.print('Read ack byte2

';);

delayMicroseconds(100);

}

void setup()

{

pinMode(ledgnd, OUTPUT);

pinMode(led, OUTPUT);

pinMode(pinIn, INPUT);

digitalWrite(led, HIGH);

digitalWrite(ledgnd, LOW);

delay(200);

digitalWrite(led, LOW);

//Serial.begin(9600);

mouse_init();

}

/*

* get a reading from the mouse and report it back to the

* host via the serial line.

*/

void loop()

{

char mstat;

char mx;

char my;

int mz;

int mi;

/* get a reading from the mouse */

mouse_write(0xeb); /* give me data! */

mouse_read(); /* ignore ack */

mstat = mouse_read();

mx = mouse_read();

my = mouse_read();

for (int thisZ = 0; thisZ < myzSize-1; thisZ++) {

myz[thisZ] = myz[thisZ+1];

}

myz[myzSize-1] = int(my);

myz[myzSize-1] = abs(myz[myzSize-1]);

mz = 0;

for (int thisZ = 0; thisZ < myzSize; thisZ++) {

mz = mz + myz[thisZ];

//Serial.println(mxz[thisZ], DEC);

}

//Serial.println(mz, DEC);

mi = digitalRead(pinIn);

//Serial.println(mi, DEC);

if ((mz < 10) and (mi == HIGH)) {

digitalWrite(led, HIGH);

}

else {

digitalWrite(led, LOW);

}

digitalWrite(ledgnd, LOW);

/* send the data back up */

//Serial.print(mstat, BIN);

//Serial.print(' X=';);

//Serial.print(mx, DEC);

//Serial.print(' Y=';);

//Serial.print(my, DEC);

//Serial.println();

delay(200); /* twiddle */

}

[/CODE]

Подпишитесь на автора

Подпишитесь на автора, если вам нравятся его публикации. Тогда вы будете получать уведомления о его новых статьях.

Отписаться от уведомлений вы всегда сможете в профиле автора.

40
Комментарии к статье