Is a parport fast enough?

More
31 Jul 2024 02:31 #306458 by JamesHoward
So heres a fun one! I was pondering..... Will a parallel port run a DAC directly?  I have an AD664-bip. It is a 4 channel 12 bit (8 pins with two words) bi-polar DAC. I had ChatGpt write up a driver for it. But before I go making up a PCB for this... What do you think??

Datasheet:
www.analog.com/media/en/technical-docume...ata-sheets/ad664.pdf

Here is the hal.ini
loadrt trivkins
loadrt motmod base_period=1000000 servo_period=1000000

# Load parallel port drivers
loadrt hal_parport cfg="0x378 out 0x278 out"

# Define DAC (AD664JN-BIP) control and data pins
net dac-data <= parport.0.pin-02-09
net dac-wr => parport.0.pin-10-out
net dac-cs => parport.0.pin-11-out

# Define quadrature encoders
net x-pos-a => parport.0.pin-12-in
net x-pos-b => parport.0.pin-13-in
net y-pos-a => parport.0.pin-14-in
net y-pos-b => parport.0.pin-15-in
net z-pos-a => parport.0.pin-16-in
net z-pos-b => parport.0.pin-17-in
net spindle-pos-a => parport.1.pin-10-in
net spindle-pos-b => parport.1.pin-11-in

# Define limit and home switches
net x-neg-limit => parport.1.pin-12-in
net x-pos-limit => parport.1.pin-13-in
net x-home => parport.1.pin-14-in

net y-neg-limit => parport.1.pin-15-in
net y-pos-limit => parport.1.pin-16-in
net y-home => parport.1.pin-17-in

net z-neg-limit => parport.1.pin-18-in
net z-pos-limit => parport.1.pin-19-in
net z-home => parport.1.pin-20-in

# Define global enable output
net global-enable => parport.0.pin-01-out

# Define GPIO pins
net gpio-in-00 <= parport.1.pin-02-in
net gpio-in-01 <= parport.1.pin-03-in
net gpio-in-02 <= parport.1.pin-04-in
net gpio-in-03 <= parport.1.pin-05-in
net gpio-in-04 <= parport.1.pin-06-in
net gpio-in-05 <= parport.1.pin-07-in

net gpio-out-00 => parport.1.pin-08-out
net gpio-out-01 => parport.1.pin-09-out
net gpio-out-02 => parport.1.pin-15-out
net gpio-out-03 => parport.1.pin-16-out
net gpio-out-04 => parport.1.pin-01-out
net gpio-out-05 => parport.1.pin-14-out

addf parport.0.read base-thread
addf parport.1.read base-thread
addf parport.0.write base-thread
addf parport.1.write base-thread

start

And here is the config:
#include "hal.h"
#include "rtapi.h"
#include "rtapi_app.h"
#include "rtapi_bitops.h"
#include "hal_parport.h"

// Define pins and parameters
static int comp_id;
static hal_float_t *x_output;
static hal_float_t *y_output;
static hal_float_t *z_output;
static hal_float_t *spindle_output;
static hal_bit_t *global_enable;
static hal_bit_t *x_home;
static hal_bit_t *y_home;
static hal_bit_t *z_home;

// Limit switches
static hal_bit_t *x_neg_limit, *x_pos_limit;
static hal_bit_t *y_neg_limit, *y_pos_limit;
static hal_bit_t *z_neg_limit, *z_pos_limit;

// Quadrature encoder positions
static hal_bit_t *x_pos_a, *x_pos_b;
static hal_bit_t *y_pos_a, *y_pos_b;
static hal_bit_t *z_pos_a, *z_pos_b;
static hal_bit_t *spindle_pos_a, *spindle_pos_b;

// GPIO pins
static hal_bit_t *gpio_in_00, *gpio_in_01, *gpio_in_02, *gpio_in_03, *gpio_in_04, *gpio_in_05;
static hal_bit_t *gpio_out_00, *gpio_out_01, *gpio_out_02, *gpio_out_03, *gpio_out_04, *gpio_out_05;

// Previous states for quadrature decoding
static int prev_x_pos = 0, prev_y_pos = 0, prev_z_pos = 0, prev_spindle_pos = 0;
// Position counters
static int x_counter = 0, y_counter = 0, z_counter = 0, spindle_counter = 0;

#define SCALE_FACTOR 204.8 // Scale factor for 12-bit DAC with ±10V range

// Lookup table for quadrature decoding
const int quad_table[16] = {
    0, -1,  1,  0,
    1,  0,  0, -1,
   -1,  0,  0,  1,
    0,  1, -1,  0
};

static void write_dac_value(uint8_t data)
{
    hal_parport_write_data(0, data);
    hal_parport_write_pin(0, 11, 0); // CS low
    hal_parport_write_pin(0, 10, 0); // WR low
    hal_parport_write_pin(0, 10, 1); // WR high
    hal_parport_write_pin(0, 11, 1); // CS high
}

static void update(void *arg, long period)
{
    uint16_t x_value = (uint16_t)((*x_output + 10.0) * SCALE_FACTOR); // Scaling from -10V to 10V
    uint16_t y_value = (uint16_t)((*y_output + 10.0) * SCALE_FACTOR);
    uint16_t z_value = (uint16_t)((*z_output + 10.0) * SCALE_FACTOR);
    uint16_t spindle_value = (uint16_t)((*spindle_output + 10.0) * SCALE_FACTOR);

    // Send data to DAC for each axis in sequence
    write_dac_value((x_value >> 4) & 0xFF); // Send upper 8 bits
    write_dac_value((x_value << 4) & 0xF0); // Send lower 4 bits

    write_dac_value((y_value >> 4) & 0xFF); // Send upper 8 bits
    write_dac_value((y_value << 4) & 0xF0); // Send lower 4 bits

    write_dac_value((z_value >> 4) & 0xFF); // Send upper 8 bits
    write_dac_value((z_value << 4) & 0xF0); // Send lower 4 bits

    write_dac_value((spindle_value >> 4) & 0xFF); // Send upper 8 bits
    write_dac_value((spindle_value << 4) & 0xF0); // Send lower 4 bits

    hal_parport_write_pin(0, 1, *global_enable);

    // Read limit and home switches
    *x_neg_limit = hal_parport_read_pin(1, 12);
    *x_pos_limit = hal_parport_read_pin(1, 13);
    *x_home = hal_parport_read_pin(1, 14);

    *y_neg_limit = hal_parport_read_pin(1, 15);
    *y_pos_limit = hal_parport_read_pin(1, 16);
    *y_home = hal_parport_read_pin(1, 17);

    *z_neg_limit = hal_parport_read_pin(1, 18);
    *z_pos_limit = hal_parport_read_pin(1, 19);
    *z_home = hal_parport_read_pin(1, 20);

    // Read quadrature encoder inputs
    int x_pos = hal_parport_read_pin(0, 12) | (hal_parport_read_pin(0, 13) << 1);
    int y_pos = hal_parport_read_pin(0, 14) | (hal_parport_read_pin(0, 15) << 1);
    int z_pos = hal_parport_read_pin(0, 16) | (hal_parport_read_pin(0, 17) << 1);
    int spindle_pos = hal_parport_read_pin(1, 10) | (hal_parport_read_pin(1, 11) << 1);

    // Quadrature decoding
    int x_delta = quad_table[(prev_x_pos << 2) | x_pos];
    int y_delta = quad_table[(prev_y_pos << 2) | y_pos];
    int z_delta = quad_table[(prev_z_pos << 2) | z_pos];
    int spindle_delta = quad_table[(prev_spindle_pos << 2) | spindle_pos];

    x_counter += x_delta;
    y_counter += y_delta;
    z_counter += z_delta;
    spindle_counter += spindle_delta;

    prev_x_pos = x_pos;
    prev_y_pos = y_pos;
    prev_z_pos = z_pos;
    prev_spindle_pos = spindle_pos;

    // Update GPIO output pins
    hal_parport_write_pin(1, 8, *gpio_out_00);
    hal_parport_write_pin(1, 9, *gpio_out_01);
    hal_parport_write_pin(1, 15, *gpio_out_02);
    hal_parport_write_pin(1, 16, *gpio_out_03);
    hal_parport_write_pin(1, 1, *gpio_out_04);
    hal_parport_write_pin(1, 14, *gpio_out_05);

    // Read GPIO input pins
    *gpio_in_00 = hal_parport_read_pin(1, 2);
    *gpio_in_01 = hal_parport_read_pin(1, 3);
    *gpio_in_02 = hal_parport_read_pin(1, 4);
    *gpio_in_03 = hal_parport_read_pin(1, 5);
    *gpio_in_04 = hal_parport_read_pin(1, 6);
    *gpio_in_05 = hal_parport_read_pin(1, 7);
}

int rtapi_app_main(void)
{
    comp_id = hal_init("my_driver");
    if (comp_id < 0)
    {
        return comp_id;
    }

    hal_pin_float_new("my_driver.x-output", HAL_OUT, &x_output, comp_id);
    hal_pin_float_new("my_driver.y-output", HAL_OUT, &y_output, comp_id);
    hal_pin_float_new("my_driver.z-output", HAL_OUT, &z_output, comp_id);
    hal_pin_float_new("my_driver.spindle-output", HAL_OUT, &spindle_output, comp_id);
    hal_pin_bit_new("my_driver.global-enable", HAL_OUT, &global_enable, comp_id);
    hal_pin_bit_new("my_driver.x-home", HAL_IN, &x_home, comp_id);
    hal_pin_bit_new("my_driver.y-home", HAL_IN, &y_home, comp_id);
    hal_pin_bit_new("my_driver.z-home", HAL_IN, &z_home, comp_id);

    hal_pin_bit_new("my_driver.x-neg-limit", HAL_IN, &x_neg_limit, comp_id);
    hal_pin_bit_new("my_driver.x-pos-limit", HAL_IN, &x_pos_limit, comp_id);
    hal_pin_bit_new("my_driver.y-neg-limit", HAL_IN, &y_neg_limit, comp_id);
    hal_pin_bit_new("my_driver.y-pos-limit", HAL_IN, &y_pos_limit, comp_id);
    hal_pin_bit_new("my_driver.z-neg-limit", HAL_IN, &z_neg_limit, comp_id);
    hal_pin_bit_new("my_driver.z-pos-limit", HAL_IN, &z_pos_limit, comp_id);

    hal_pin_bit_new("my_driver.x-pos-a", HAL_IN, &x_pos_a, comp_id);
    hal_pin_bit_new("my_driver.x-pos-b", HAL_IN, &x_pos_b, comp_id);
    hal_pin_bit_new("my_driver.y-pos-a", HAL_IN, &y_pos_a, comp_id);
    hal_pin_bit_new("my_driver.y-pos-b", HAL_IN, &y_pos_b, comp_id);
    hal_pin_bit_new("my_driver.z-pos-a", HAL_IN, &z_pos_a, comp_id);
    hal_pin_bit_new("my_driver.z-pos-b", HAL_IN, &z_pos_b, comp_id);
    hal_pin_bit_new("my_driver.spindle-pos-a", HAL_IN, &spindle_pos_a, comp_id);
    hal_pin_bit_new("my_driver.spindle-pos-b", HAL_IN, &spindle_pos_b, comp_id);

    hal_pin_bit_new("my_driver.gpio-in-00", HAL_IN, &gpio_in_00, comp_id);
    hal_pin_bit_new("my_driver.gpio-in-01", HAL_IN, &gpio_in_01, comp_id);
    hal_pin_bit_new("my_driver.gpio-in-02", HAL_IN, &gpio_in_02, comp_id);
    hal_pin_bit_new("my_driver.gpio-in-03", HAL_IN, &gpio_in_03, comp_id);
    hal_pin_bit_new("my_driver.gpio-in-04", HAL_IN, &gpio_in_04, comp_id);
    hal_pin_bit_new("my_driver.gpio-in-05", HAL_IN, &gpio_in_05, comp_id);

    hal_pin_bit_new("my_driver.gpio-out-00", HAL_OUT, &gpio_out_00, comp_id);
    hal_pin_bit_new("my_driver.gpio-out-01", HAL_OUT, &gpio_out_01, comp_id);
    hal_pin_bit_new("my_driver.gpio-out-02", HAL_OUT, &gpio_out_02, comp_id);
    hal_pin_bit_new("my_driver.gpio-out-03", HAL_OUT, &gpio_out_03, comp_id);
    hal_pin_bit_new("my_driver.gpio-out-04", HAL_OUT, &gpio_out_04, comp_id);
    hal_pin_bit_new("my_driver.gpio-out-05", HAL_OUT, &gpio_out_05, comp_id);

    rtapi_snprintf(name, sizeof(name), "my_driver.update");
    hal_periodic_func_new(update, NULL, 1000000);

    hal_ready(comp_id);
    return 0;
}

void rtapi_app_exit(void)
{
    hal_exit(comp_id);
}

Please Log in or Create an account to join the conversation.

More
31 Jul 2024 03:17 #306459 by cornholio
Replied by cornholio on topic Is a parport fast enough?
It's rubbish. ChatGPT is stupid, on levels that will get we banned for even mentioning.

The config seems to a driver. That doesn't seem to be loaded. There's bits for quad encoders, spindle. It's like it's just thrown stuff together. There appears to be no consideration given to timing of signals.

What exactly do you want to do ?

If you just want to use a DAC in non real time there are so many other ways to do it without needing Linuxcnc.
The following user(s) said Thank You: meister

Please Log in or Create an account to join the conversation.

More
31 Jul 2024 05:06 - 31 Jul 2024 05:08 #306461 by JamesHoward
I know Chats algo's arent perfect.. Its like a highschooler still. It is a good base to start from tho. I actually have a seperate encoder card for the computer. I just had it throw it in there... But I sure like not having not to type all that out! Especially for something that might not even be good enough! Yes I would like to have real time! Of course!

I am looking to have real +-10 v for my servo drives. That is the end goal. I just have this DAC kicking around, I figured it could be of good use being bi-polar and all..... I have a 3 axis mill. I and not interested in changing the drives or motors. These puppies are 10 HP. I like to cut FAST! :dry: 
Last edit: 31 Jul 2024 05:08 by JamesHoward.

Please Log in or Create an account to join the conversation.

More
31 Jul 2024 06:19 #306463 by cornholio
Replied by cornholio on topic Is a parport fast enough?
It's not even a base, its mumbo jumbo.

Please Log in or Create an account to join the conversation.

More
31 Jul 2024 07:14 #306465 by JamesHoward
well... thanks for your help

Please Log in or Create an account to join the conversation.

More
31 Jul 2024 07:35 #306468 by cornholio
Replied by cornholio on topic Is a parport fast enough?
I'm sorry mate, but that is what it is.

To begin with the ini has the make up of a hal file.

The "config" file is more like a driver file (linuxcnc uses ini & hal files). If it was to be a driver, it's not loaded, it's not added to any threads, so it wont do anything.

The timing for writing for writing to the "DAC" is unlikely to be met. You'll need two Parallel Port interfaces, and it's very rare to find a computer with 2 on board interfaces. The last time I saw a machine with Parallel Ports at 0x378 & 0x278 was old an old ISA bus machine where the cards needed to be configured by jumpers.

Now there are ways to control analogue servo drives, but the parallel port is not the way route to choose.

Now what I would suggest is to start a new topic asking the best way to control analogue servo drives. And lets leave this whole ChatGPT nonense behind us.

I would also recommend reading the documentation to get a feel of the basics.
The following user(s) said Thank You: Aciera

Please Log in or Create an account to join the conversation.

More
31 Jul 2024 07:44 #306471 by tommylight
To many things wrong there
-parallel port can NOT do all inputs in any of it's modes
-parallel port has 17 I/O in total, there are inputs 18 and 19 mentioned on the first post
so i agree with Cornholio, it is rubbish and will waste more time than asking humans
-
Parallel port can do
-mode out = 12 out 5 in
-mode in = 13 in 4 out
-mode X = 8 out 9 in
And LinuxCNC can control multiple at the same time.
The following user(s) said Thank You: Aciera, cornholio

Please Log in or Create an account to join the conversation.

More
31 Jul 2024 09:21 #306479 by Aciera
Replied by Aciera on topic Is a parport fast enough?

well... thanks for your help


I'm sorry but it's just like last time you asked for advice here:
forum.linuxcnc.org/27-driver-boards/5109...17x0?start=10#288989

You turn up with some hallucination and expect other people to make it come true for you.
The following user(s) said Thank You: tommylight, cornholio

Please Log in or Create an account to join the conversation.

More
31 Jul 2024 10:02 #306486 by tommylight
Just get some cheap TB6600 drives, wire those directly to an old PC with parallel port, make the machine move.
No AI will help you with that, yet.

Please Log in or Create an account to join the conversation.

More
31 Jul 2024 12:34 #306514 by cornholio
Replied by cornholio on topic Is a parport fast enough?
Sarcasm will defeat AI.
Have your Memes at the ready.

Please Log in or Create an account to join the conversation.

Time to create page: 0.133 seconds
Powered by Kunena Forum