Мой прожектикъ
По ценам.
Электроника (вся: контроллер + 4 движка + 4 муфты) в пуре - 10 тыщ.
Направляющие 16мм + направляющие 25мм + подшипниковые блоки под 25мм (разрезанные) - в пуре, не помню точно, вроде около 3 тысяч.
ШВП + гайки + обработка концов + доставка - 500 УЕ с доставкой (можно было бы и дешевле, но ступил. Надо было в Китае все это заказывать, а заказал в Тайване).
Опоры 16мм (8 штук) - 40 баксов, доставка - лично 😉 Можно было опоры не по 5, а по 3.5 бакса, но тогда доставка под 70 УЕ.
Дюраль - материал + изготовление деталей - 11 тыс рублей.
Крепеж - около тысячи рублей весь.
Самопиленные вещи - модбас, проставки для двигателей.
Доска - полторы тысячи рублей.
Подшпники для опор ШВП - 16 штук по 40 рублей (по нынешним ценам, я у друзей половину бесплатно забрал 😉)
Общий вывод: Нужно все готовые детали (направляющие, подшипники, винты, крепеж, моторы,…) заказывать в Китае. Даже с доставкой и честной растаможкой оно будет минимум в 3 раза дешевле, чем покупать в Москве.
Ходы: Z:80мм, Y: 340, X: 540
Меня по оси X катает легко 😉
Попытался представить😂😂😂
Попытался представить😂😂😂
Очень, в самом деле, страшно: стоять приходится на цыпочках, и эта дура сама собой едет 😉
Поздравляю. Но крепление нарпавляющих я бы зделал также как у вас шпиндель. Тоесть в клипсу, много надежней и после многих разборок сборок будет всеравно хорошо держать. Ну и станину я думаю современем сделаете чтото из металла, а то деревяную нуно будет менять часто, да и от смены влажности крутить будет.
Поскольку на пурелоджиковом контроллере было всего 4 входа, да и те работали через пень-колоду, пришлось наговнякать по-быстрому modbus-контроллер. Тут тоже “сын ошибок трудных” был постижен 😉 😉, но результат вцелом устраивает:
Можно подробнее о пурелоджиковом контроллере? Что именно не так?
И, извините за дремучесть, что такое- modbus-контроллер?😃
поделитемь ссылкой на швп в тиайване и катае если не трудно
очень интересно посмотреть на их цены
кстати, мне нравится ваша простота конструкции
Отвечаю по порядку.
по поводу крепления направляющих - согласен, узел одноразовый. Но я если и задумаю менять что-то, то это будет в новой конструкции. Там - да, сделаю клипсу.
Станина эта - тоже решение “временно-постоянное”. Т.е. если меня не устроит жесткость-вибропоглощающая способность этой станины, то буду лить из эпоксидки с наполнителем. К сожалению, для конструирования станины из металла нет ни навыков, ни инструмента.
Про контроллер. Не так - как-то странно работают входы, точнее, то работают, то не работают. Выходы работают тип-топ. Да, кроме этого, входы сделаны не как “сухие контакты”, а как входы оптопар (диоды), поэтому нужен еще один источник питания.
Модбас-контроллер - в общем-то в моей реализации это Mega16 (которая была под рукой) с 8 входами и 8 выходами. Выходы и выходы относительно меги не отвязаны, вместо этого 2-мя оптопарами отвязан MAX232. Со стороны компутера задействуется КОМ-порт, в Mach3 прекрасно работает совместно с “мозгами”.
Насчет ссылки на ШВП в тайване - я где-то уже давал тут ссылку. Вкрадце - идите на alibaba.com, регьтесь там, ищите ШВП, и дальше - личное общение с продавцом. Разница в цене между Китаем и Тайванем может составлять до 3-х раз. Мне обошлось вот в это:
1605 or 1604 nut: USD42/pcs[/COLOR]
1605 or 1604 shaft
350mm: USD13.5/pcs
540mm: USD20.5/pcs
810mm: USD31/pcs
Machining cost for 1 end: USD15 Do you need end-machining for every "end"? Then, the total cost for end -machining will be USD15*8=USD120
Total goods cost: 120+42*4+13.5+20.5+31*2=USD384; product lead time: 10 days
Delivery cost by EMS: USD115; delivery 1 week after shipment.
Total: USD384+115=USD499 100% TT in advance
Платилось через WeternUnion. Лавка - вот эта www.lexem.com.tw но там все на неясном мне диалекте 😉 😉, поэтому чертежи мне присылались в почту.
Почему крепеж линейных подшипников по Х только на двух болтах? Предусмотрено ж 4… так было бы жоще…
А как направляющие крепятся в опорах? Как-то стопорных болтов не видно… ни разреза…
Ой, не доглядел… на четырех… только по мойму все-таки жоще было бы непосредственно линейные подш. крепить к боковинам, без “переходной” пластины.
Ой, не доглядел… на четырех… только по мойму все-таки жоще было бы непосредственно линейные подш. крепить к боковинам, без “переходной” пластины. google_ad_section_end
А опоры направляющих???
Модбас-контроллер - в общем-то в моей реализации это Mega16 (которая была под рукой) с 8 входами и 8 выходами. Выходы и выходы относительно меги не отвязаны, вместо этого 2-мя оптопарами отвязан MAX232. Со стороны компутера задействуется КОМ-порт, в Mach3 прекрасно работает совместно с “мозгами”.
Про Modbus можно поподробнее, или коммерция?
Если я правильно понял вопрос, то опоры направляющих Х - 8 саморезов на штуку.
Модбас - легко. Софт - freemodbus, плюс плата с косяками 😉 Если интересно, могу выложить “модификацию” софта (на самом деле, там все очень просто и прозрачно) и плату.
Если я правильно понял вопрос, то опоры направляющих Х - 8 саморезов на штуку.
Модбас - легко. Софт - freemodbus, плюс плата с косяками 😉 Если интересно, могу выложить “модификацию” софта (на самом деле, там все очень просто и прозрачно) и плату.
Конечно интересно, да если можно со своими комментами или пояснениями, я в принципе так и думал, но для меня freemodbus темный лес.
Про контроллер. Не так - как-то странно работают входы, точнее, то работают, то не работают.
Вы же вроде в Москве? Не пробовали связаться на сей счёт с Purelogic-ами?
Вы же вроде в Москве? Не пробовали связаться на сей счёт с Purelogic-ами?
Если у вас Пурложик, то же проблемы будут!
Вы же вроде в Москве? Не пробовали связаться на сей счёт с Purelogic-ами?
Все из-за того что в опторазвязке оптопары медленные походу.
Если у вас Пурложик, то же проблемы будут!
Можно подробнее?
У меня электроника от Пурелогиков, пока занимаюсь механикой электронику не подключал. Хотелось бы знать все мнения. Негатива по поводу Пурелогиков в Сети не встречал…
У меня PLC002 - работает хорошо .
Модбас.
test.c из demo/avr:
/*
* FreeModbus Libary: AVR Demo Application
* Copyright (C) 2006 Christian Walter <>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* File: $Id: demo.c,v 1.7 2006/06/15 15:38:02 wolti Exp $
*/
/* ----------------------- AVR includes -------------------------------------*/
#include "avr/io.h"
#include "avr/interrupt.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"
#include "delay.h"
/* ----------------------- Defines ------------------------------------------*/
#define REG_INPUT_START 1000
#define REG_INPUT_NREGS 4
#define REG_COILS_START 1100
#define REG_COILS_SIZE 8
#define REG_DISC_START 1200
#define REG_DISC_SIZE 8
#define REG_HOLDING_START 1300
#define REG_HOLDING_NREGS 8
/* ----------------------- Static variables ---------------------------------*/
static USHORT usRegInputStart = REG_INPUT_START;
static USHORT usRegInputBuf[REG_INPUT_NREGS];
static UCHAR ucRegCoilsBuf[REG_COILS_SIZE / 8];
static UCHAR ucRegDiscBuf[REG_DISC_SIZE / 8 ];
static USHORT usRegHoldingStart = REG_HOLDING_START;
static USHORT usRegHoldingBuf[REG_HOLDING_NREGS];
static CHAR cEncoderTimer=0;
static CHAR cDirCur,cDirPrev;
static UCHAR ucEncoderCur=0;
static UCHAR ucEncoderPrev=0;
static CHAR cDecoded;
static CHAR cDecodedPrev;
/* Gray-code convertion table */
const unsigned char GrayCode[16]=
{
0,2,1,0,
1,0,0,2,
2,0,0,1,
0,1,2,0
};
#ifndef outb
#define outb(addr, data) addr = (data)
#endif
#ifndef inb
#define inb(addr) (addr)
#endif
#ifndef outw
#define outw(addr, data) addr = (data)
#endif
#ifndef inw
#define inw(addr) (addr)
#endif
#ifndef BV
#define BV(bit) (1<<(bit))
#endif
#ifndef cbi
#define cbi(reg,bit) reg &= ~(BV(bit))
#endif
#ifndef sbi
#define sbi(reg,bit) reg |= (BV(bit))
#endif
#ifndef cli
#define cli() __asm__ __volatile__ ("cli" ::)
#endif
#ifndef sei
#define sei() __asm__ __volatile__ ("sei" ::)
#endif
#define INPUT_DDR DDRB
#define INPUT_PIN PINB
#define INPUT_PORT OUTPUT_PORT
#define OUTPUT_DDR DDRC
#define OUTPUT_PIN PINC
#define OUTPUT_PORT PORTC
/* ----------------------- Start implementation -----------------------------*/
int
main( void )
{
const UCHAR ucSlaveID[] = { 0xAA, 0xBB, 0xCC };
eMBErrorCode eStatus;
OUTPUT_DDR=0xFF;
INPUT_DDR=0x00;
OUTPUT_PORT=0xAA;
delay_ms(1000);
OUTPUT_PORT=0xff;
eStatus = eMBInit( MB_RTU, 0x0A, 0, 4800, MB_PAR_NONE );
OUTPUT_PORT=eStatus;
delay_ms(1000);
OUTPUT_PORT=0xff;
eStatus = eMBSetSlaveID( 0x34, TRUE, ucSlaveID, 3 );
OUTPUT_PORT=eStatus;
delay_ms(1000);
OUTPUT_PORT=0xff;
sei( );
/* Enable the Modbus Protocol Stack. */
eStatus = eMBEnable( );
OUTPUT_PORT=eStatus;
delay_ms(1000);
OUTPUT_PORT=0xff;
/* Init encoder */
usRegHoldingBuf[0]=0;
// set interrupt pins to input and apply pullup resistor
cbi(DDRD, PD2);
sbi(PORTD, PD2);
// set encoder direction pin for input and apply pullup resistor
cbi(DDRD, PD4);
sbi(PORTD, PD4);
cDirCur=cDirPrev=0;
usRegHoldingBuf[0]=100;
for( ;; )
{
( void )eMBPoll( );
OUTPUT_PORT = ucRegCoilsBuf[0];
ucRegDiscBuf[0]=INPUT_PIN;
/* Here we simply count the number of poll cycles. */
usRegInputBuf[0]++;
/* Process Encoder */
/* Save the previouse encoder state */
ucEncoderPrev = ucEncoderCur;
/* Get current encoder value*/
ucEncoderCur = ((PIND>>2) + ((PIND>>4)<<1)) & 0x03;
/* Check if the state has changed */
if (ucEncoderCur != ucEncoderPrev)
{
cDecoded = GrayCode[(ucEncoderPrev<<2) | ucEncoderCur];
/* Check if the direction has changed */
if (cDecoded == cDecodedPrev)
{
/* The direction is the same, decrease the timer */
cEncoderTimer++;
}
else
{
/* The direction has changed, load the timer */
cEncoderTimer=0;
cDecodedPrev = cDecoded;
}
if ((cEncoderTimer == 3) && (cDecoded != 0))
{
/* The direction is stable for 4 periods, change the counter */
cDecodedPrev=0;
cEncoderTimer = 0;
if (cDecoded == 0x1)
usRegHoldingBuf[0]++;
if (cDecoded == 0x02)
usRegHoldingBuf[0]--;
}
}
}
}
eMBErrorCode
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
eMBErrorCode eStatus = MB_ENOERR;
int iRegIndex;
if( ( usAddress >= REG_INPUT_START )
&& ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
{
iRegIndex = ( int )( usAddress - usRegInputStart );
while( usNRegs > 0 )
{
*pucRegBuffer++ =
( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
*pucRegBuffer++ =
( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
iRegIndex++;
usNRegs--;
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
eMBRegisterMode eMode )
{
eMBErrorCode eStatus = MB_ENOERR;
short iNCoils = ( short )usNCoils;
unsigned short usBitOffset;
/* Check if we have registers mapped at this block. */
if( ( usAddress >= REG_COILS_START ) &&
( usAddress + usNCoils <= REG_COILS_START + REG_COILS_SIZE ) )
{
usBitOffset = ( unsigned short )( usAddress - REG_COILS_START );
switch ( eMode )
{
/* Read current values and pass to protocol stack. */
case MB_REG_READ:
while( iNCoils > 0 )
{
*pucRegBuffer++ =
xMBUtilGetBits( ucRegCoilsBuf, usBitOffset,
( unsigned char )( iNCoils >
8 ? 8 :
iNCoils ) );
iNCoils -= 8;
usBitOffset += 8;
}
break;
/* Update current register values. */
case MB_REG_WRITE:
while( iNCoils > 0 )
{
xMBUtilSetBits( ucRegCoilsBuf, usBitOffset,
( unsigned char )( iNCoils > 8 ? 8 : iNCoils ),
*pucRegBuffer++ );
iNCoils -= 8;
}
break;
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
eMBErrorCode
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
eMBErrorCode eStatus = MB_ENOERR;
short iNDiscrete = ( short )usNDiscrete;
UCHAR * pucRegDiscBuf = ucRegDiscBuf;
/* Check if we have registers mapped at this block. */
if( ( usAddress >= REG_DISC_START ) &&
( usAddress + usNDiscrete <= REG_DISC_START + REG_DISC_SIZE ) )
{
while( iNDiscrete >> 3 )
{
*pucRegBuffer++ = *pucRegDiscBuf;
iNDiscrete -= 8;
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
eMBErrorCode
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
{
eMBErrorCode eStatus = MB_ENOERR;
int iRegIndex;
if( ( usAddress >= REG_HOLDING_START ) &&
( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
{
iRegIndex = ( int )( usAddress - usRegHoldingStart );
switch ( eMode )
{
/* Pass current register values to the protocol stack. */
case MB_REG_READ:
while( usNRegs > 0 )
{
*pucRegBuffer++ = ( UCHAR ) ( usRegHoldingBuf[iRegIndex] >> 8 );
*pucRegBuffer++ = ( UCHAR ) ( usRegHoldingBuf[iRegIndex] & 0xFF );
iRegIndex++;
usNRegs--;
}
break;
/* Update current register values with new values from the
* protocol stack. */
case MB_REG_WRITE:
while( usNRegs > 0 )
{
usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
iRegIndex++;
usNRegs--;
}
break;
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
delay.h:
#ifndef _delay_h_
#define _delay_h_
#include <inttypes.h>
#include <avr/io.h>
/* delay function for microsec
4 cpu cycles per loop + 1 cycles(?) overhead
when a constant is passed. */
static inline void delayloop16(uint16_t count)
{
asm volatile ( "cp %A0,__zero_reg__ \n\t" \
"cpc %B0,__zero_reg__ \n\t" \
"breq L_Exit_%= \n\t" \
"L_LOOP_%=: \n\t" \
"sbiw %0,1 \n\t" \
"brne L_LOOP_%= \n\t" \
"L_Exit_%=: \n\t" \
: "=w" (count)
: "0" (count)
);
}
// delayloop16(x) eats 4 cycles per x
#define DELAY_US_CONV(us) ((uint16_t)(((((us)*1000L)/(1000000000/F_CPU))-1)/4))
#define delay_us(us) delayloop16(DELAY_US_CONV(us))
/* delay function for millisec
(6 cycles per x + 20(?) overhead) */
void delayloop32( uint32_t l); // not inline
#define DELAY_MS_CONV(ms) ( (uint32_t) (ms*(F_CPU/6000L)) )
#define delay_ms(ms) delayloop32(DELAY_MS_CONV(ms))
/* mth 9/04:
Remark uSeconds:
Main Oscillator Clock given by F_CPU (makefile) in Hz
one CPU-Cycle takes 1/F_CPU seconds => 1000000/F_CPU uSeconds
so: 1 uSecond takes F_CPU/1000000 CPU-Cyles. The following code
is inspired by the avr-libc delay_loop2 function.
This it not "that precise" since it takes at least 4 cycles
but should be o.k. with any parameter (even 0).
Call function with delayloop(DELAYUS(dt [in uSeconds])).
*/
#endif
В test.c есть кусок (/* Process Encoder */) обработки энкодера, подключенного к пинам PD4 и PD6, но поразмыслив (в основном о том, где я буду в Москве брать MPG) решил в железе не реализовывать. Если кто воспользуется - буду рад 😉
Разводка лежит тут: nigde.ru/modbus3.lay
При этом кварц не используется (юзаю встроенный генератор на 8МГц), скорость - 4800 (нужно осцилоскопом поглядеть фронты и поискать более быстродействующие оптопары), но меня устраивает 😉
Изготавливалось методом фотолитографии на сухой фоторезист, получится ли изготовить ЛУТом - не знаю, думаю, что да.
Kitsok,
-
насчёт модбаса - тема очень интересная. Производительности его хватает?
-
Вы как-то будете защищать винт ШВП и направляющие от попадания стружки? Насколько это вобще необходимо/желательно?
to all:
- я пока делаю управление для станка. Изначально хотел расположить драйверы двигателей в непосредственной близости к ШД. Рядом поставить - не проблема. Сейчас много драйверов, практически не греющихся, на полевиках. Остаётся вопрос: есть ли в этом какой-то смысл.
avric, Производительности 100% хватает на 38400, на 4800 его хватит для аварийной остановки в случае попытки самоубийства станка (концевики на осях + E-Stop). Конечно, калибровать home на 4800 будет очень медленно.
Защищать ШВП очень и очень желательно, но я пойду другим путем - рядом со шпинделем будет пылесос 😉
Насчет выноса силовой части поближе к ШД - ни больших минусов ни плюсов не вижу, вполне имеющая право на существование схема.
Спасибо. Вопрос, как определяются выходы Dir и Step?