Re: [comedi] PWM configuration on advantech PCI1760
Ian Abbott <[email protected]> Tue, 3 Jan 2023 13:42:48 +0000
| Newsgroups | gmane.linux.comedi |
|---|---|
| Organization | MEV Ltd. |
| Message-ID | <[email protected]> |
On 19/12/2022 15:11, Federico Alfatti wrote:
> Hello everybody,
> I hope that there is someone here that can help me.
>=20
> I am trying to generate a PWM signal from the advantech PCI1760 card. I=
=20
> am using Ubuntu 22.04.1 LTS.
> Running the=C2=A0 following code:
>=20
> /sbin/modprobe comedi
> /sbin/modprobe pci1760
> /usr/sbin/comedi_config /dev/comedi0 pci1760
>=20
> The last command returns that the device is already configured.
>=20
> At this point, taking inspiration from the pwm.c file from comedilib=20
> demo folder, I am trying to configure the PWM channel via instructions=20
> and then sending a comedi_data_write, but it seems to not accept my=20
> inputs: the function comedi_do_insn always returns error, no matter what=
=20
> INSN_CONFIG I am using.
>=20
> The device is correctely installed because I am able to both read and=20
> write on the other two DI/DO subdevices. However, I reckon I might be=20
> missing something on the INSN_CONFIG command for the pwm.
> I attach the comedi_board_info results and the code I am running.
> The "max data value" associated with the PWM subdevice 2 is 0, which=20
> seems strange to me: for my understanding, this value should represent=20
> the maximum resolution for the PWM, which in this specific case should=20
> be 2^16 (65535).
>=20
> Lastly, I read a "SDF_MODE0: can do mode 0". This should be an=20
> indication to the possible counter mode,=C2=A0 UP_COUNTER? Is there somet=
hing=20
> that I am missing or that I am not configuring?
>=20
> Is there anybody that could help, or that have some specific experience=
=20
> with the PWM control of this board? It would be really useful since I am=
=20
> struggling on this problem, and I am not able to find any documentation=
=20
> that could help me.
>=20
> Thank you very much for your time,
> Kind regards,
>=20
> Federico
>=20
> //////////////////// comedi_board_info -v ////////////////////////
>=20
> overall info:
> =C2=A0 version code: 0x00074c
> =C2=A0 driver name: adv_pci1760
> =C2=A0 board name: adv_pci1760
> =C2=A0 number of subdevices: 4
> subdevice 0:
> =C2=A0 type: 3 (digital input)
> =C2=A0 flags: 0x00010000
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 SDF_READABLE:subdevice can be read
> =C2=A0 number of channels: 8
> =C2=A0 max data value: 1
> =C2=A0 ranges:
> =C2=A0 =C2=A0 all chans: [0 V,5 V]
> =C2=A0 command:
> =C2=A0 =C2=A0 not supported
> subdevice 1:
> =C2=A0 type: 4 (digital output)
> =C2=A0 flags: 0x00020000
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 SDF_WRITABLE:subdevice can be written
> =C2=A0 number of channels: 8
> =C2=A0 max data value: 1
> =C2=A0 ranges:
> =C2=A0 =C2=A0 all chans: [0 V,5 V]
> =C2=A0 command:
> =C2=A0 =C2=A0 not supported
> subdevice 2:
> =C2=A0 type: 12 (pwm)
> =C2=A0 flags: 0x00000080
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 SDF_MODE0:can do mode 0
> =C2=A0 number of channels: 2
> =C2=A0 max data value: 0
> =C2=A0 ranges:
> =C2=A0 =C2=A0 all chans: [0,1]
> =C2=A0 command:
> =C2=A0 =C2=A0 not supported
> subdevice 3:
> =C2=A0 type: 0 (unused)
>=20
>=20
> //////////////////////////////PROGRAM////////////////////////////////////=
/////
>=20
> #include <stdio.h>
> #include <comedilib.h>
> #define N_SAMPLE 3
>=20
> char *filename=3D"/dev/comedi0";
> comedi_t *device;
> int subdevice =3D 2;
> int channel =3D 0;
> int aref;
> int range =3D 0;
>=20
> int main(int argc, char *argv[])
> {
> lsampl_t data[N_SAMPLE];
>=20
> int ret, i;
>=20
> int n_channels, n_range;
>=20
> device =3D comedi_open(filename);
> if(!device){
> printf("E: comedi_open(\"%s\") NOT SUCCESSFUL",filename);
> }
>=20
> /*Configure PWM*/
> comedi_insn insn;
>=20
> data[0] =3D INSN_CONFIG_ARM;
> data[1] =3D 0;
> =C2=A0 =C2=A0 insn.subdev =3D subdevice;
> =C2=A0 =C2=A0 insn.insn =3D INSN_CONFIG;
> =C2=A0 =C2=A0 insn.n =3D 3;
> =C2=A0 =C2=A0 insn.chanspec =3D CR_PACK(channel, range, 0);
> =C2=A0 =C2=A0 insn.data =3D data;
>=20
> ret =3D comedi_do_insn(device,&insn); //This command is always returning =
-1
> printf("\n\nconfig arm %d\n\n",ret);
>=20
> /* Activate PWM */
> ret =3D comedi_data_write(device,subdevice,channel,0,0,10); //This comman=
d=20
> is always returning -1
> printf("write %d\n\n",ret);
>=20
> comedi_close(device);
> return 0;
> }
Sorry for the long delay in replying.
It seems that the PWM subdevice for the PCI1760 needs to be operated=20
differently to the PWM subdevice on some other devices. On the PCI1760=20
PWM subdevice, all operations are done using the INSN_CONFIG instruction:
* INSN_CONFIG_PWM_OUTPUT - disables PWM output and sets PWM high and low=20
periods in nanoseconds:
lsampl_t data[5];
comedi_insn insn;
insn.subdev =3D 2; // PWM subdevice
insn.insn =3D INSN_CONFIG;
insn.chanspec =3D channel; // 0 or 1
insn.n =3D 5;
insn.data =3D data;
data[0] =3D INSN_CONFIG_PWM_OUTPUT;
// set rounding for high period
data[1] =3D CMDF_ROUND_NEAREST; // or CMDF_ROUND_UP or CMDF_ROUND_DOWN
data[2] =3D high_ns; // high period in ns
// set rounding for low period
data[3] =3D CMDF_ROUND_NEAREST; // or CMDF_ROUND_UP or CMDF_ROUND_DOWN
data[4] =3D low_ns; // low period in ns
ret =3D comedi_do_insn(device, &insn);
Note: on success, data[2] and data[4] are set to the rounded high and=20
low periods.
* INSN_CONFIG_ARM - enables PWM output and sets number of cycles or=20
"continuous":
lsampl_t data[2];
comedi_insn insn;
insn.subdev =3D 2; // PWM subdevice
insn.insn =3D INSN_CONFIG;
insn.chanspec =3D channel; // 0 or 1
insn.n =3D 2;
insn.data =3D data;
data[0] =3D INSN_CONFIG_ARM;
data[1] =3D 0; // 0 =3D "continuous", 1 to 65535 =3D number of cycles
ret =3D comedi_do_insn(device, &insn);
* INSN_CONFIG_DISARM - disables PWM output:
lsampl_t data[1];
comedi_insn insn;
insn.subdev =3D 2; // PWM subdevice
insn.insn =3D INSN_CONFIG;
insn.chanspec =3D channel; // 0 or 1
insn.n =3D 1;
insn.data =3D data;
data[0] =3D INSN_CONFIG_DISARM;
ret =3D comedi_do_insn(device, &insn);
* INSN_CONFIG_GET_PWM_OUTPUT - get configured high and low periods:
lsampl_t data[3];
comedi_insn insn;
insn.subdev =3D 2; // PWM subdevice
insn.insn =3D INSN_CONFIG;
insn.chanspec =3D channel; // 0 or 1
insn.n =3D 3;
insn.data =3D data;
data[0] =3D INSN_CONFIG_GET_PWM_OUTPUT;
ret =3D comedi_do_insn(device, &insn);
On success, the high period is in data[1] and the low period is in=20
data[2].
* INSN_CONFIG_GET_PWM_STATUS - get PWM status:
lsampl_t data[2];
comedi_insn insn;
insn.subdev =3D 2; // PWM subdevice
insn.insn =3D INSN_CONFIG;
insn.chanspec =3D channel; // 0 or 1
insn.n =3D 2;
insn.data =3D data;
data[0] =3D INSN_CONFIG_GET_PWM_STATUS;
ret =3D comedi_do_insn(device, &insn);
On success, the enable/disable status in in data[1].
Unfortunately, there seems to be a bug in the driver which probably=20
stops most of the above instructions from working. The problem is that=20
the driver is sending wrong command code to read the PWM status=20
register. In the driver code at=20
<https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/dr=
ivers/comedi/drivers/adv_pci1760.c?h=3Dv6.1>=20
the PCI1760_CMD_GET_STATUS macro should be defined as 0x07, not 0x03.=20
I'll send a patch to the Linux kernel mailing lists to get it fixed, but=20
it will be some time before it makes its way into the stable kernel=20
versions.
--=20
-=3D( Ian Abbott <[email protected]> || MEV Ltd. is a company )=3D-
-=3D( registered in England & Wales. Regd. number: 02862268. )=3D-
-=3D( Regd. addr.: S11 & 12 Building 67, Europa Business Park, )=3D-
-=3D( Bird Hall Lane, STOCKPORT, SK3 0XA, UK. || www.mev.co.uk )=3D-
--=20
You received this message because you are subscribed to the Google Groups "=
Comedi: Linux Control and Measurement Device Interface" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to [email protected].
To view this discussion on the web visit https://groups.google.com/d/msgid/=
comedi_list/8c7a9db6-c092-d0c2-5633-49b340a7c265%40mev.co.uk.