Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 01:57 17 May 2022 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : maximite and GPIB/IEEE-488

Author Message
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 1987
Posted: 04:25am 04 Jan 2013
Copy link to clipboard 
Print this post

hi,
first posting here, though i've been following the maximite for quite a while, with a view to using it as an instrument controller.

has anyone looked at adding GPIB/IEEE-488 (HPIB) via the arduino connectors on the colour maximite, and writing the appropriate extensions to the basic? this would produce a neat little instrument controller that would be completely unique (as a modern product) and perhaps even highly desirable/marketable.

the idea of using the arduino connectors would be to then have the GPIB connector mounted on the rear panel, leaving the 20 I/O pins on the expansion connector for controlling relays - another important part of any instrument controller.

cheers,
rob :-)

 
CircuitGizmos

Guru

Joined: 08/09/2011
Location: United States
Posts: 1416
Posted: 04:56am 04 Jan 2013
Copy link to clipboard 
Print this post

Is there an HPIB shield made by anyone?
Micromites and Maximites! - Beginning Maximite
 
TinkersALot
Regular Member

Joined: 20/11/2012
Location: United States
Posts: 72
Posted: 07:26am 04 Jan 2013
Copy link to clipboard 
Print this post

  CircuitGizmos said   Is there an HPIB shield made by anyone?


I searched here:

http://shieldlist.org/

for "HPIB" and came up with nothing, but I do not know if there is a better "all known shields" site that would offer better results.
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 1987
Posted: 12:14pm 04 Jan 2013
Copy link to clipboard 
Print this post

as far as i am aware, nobody makes one, but electrically the interface is quite simple. TTL signalling, an 8-bit bidirectional data bus, and another 8 control lines:
EOI End-or-identify
DAV Data valid
NRFD Not ready for data
NDAC Not data accepted
IFC Interface clear
SRQ Service request
ATN Attention
REN Remote enable

people have made GPIB to serial converters using just the i/o pins on a (5 volt) pic directly. but the devil is in the details - without some 'intelligence' in a controller is can be quite complicated to manage the bus, hence the bigger part of the job being writing the basic extensions.

just a GPIB to USB converter starts at several hundred dollars for a commercial product.
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 2765
Posted: 12:01am 05 Jan 2013
Copy link to clipboard 
Print this post

Surely a GPIB-USB converter starts very cheaply such as this http://www.dalton.ax/gpib/

It would be easily changed from USB to another interface (RS232 or whatever) and could then connect to a 'mite.

I have to say I don't see much interest for doing this so I reckon DIY :)

John
 
boss

Senior Member

Joined: 19/08/2011
Location: Canada
Posts: 268
Posted: 07:02am 05 Jan 2013
Copy link to clipboard 
Print this post

Hi,

I'm considering to work with GPIB as well, and I found on the web this source code:


http://bananawani-mc.blogspot.ca/2010/09/arduinogpib.html


/*
* GIPB Ether Adapter
*/

#include <string.h>
#include <Ethernet.h>

// Define PIN name
#define DIO1 19
#define DIO2 18
#define DIO3 17
#define DIO4 16
#define DIO5 15
#define DIO6 14
#define DIO7 9
#define DIO8 8
#define EOI 6
#define DAV 5
#define NRFD 4
#define NDAC 3
#define IFC 7
#define ATN 2
#define REN GND
#define SRQ GND

// set MAC & IP
byte mac[] = { 0xZZ, 0xZZ, 0xZZ, 0xZZ, 0xZZ, 0xZZ };
byte ip[] = { ZZZ, ZZZ, ZZZ, ZZZ };
byte gateway[] = { ZZZ, ZZZ, ZZZ, ZZZ };
byte subnet[] = { ZZZ, ZZZ, ZZZ, ZZZ };
Server server(ZZZ);

// set Commando val
char com[256] = "";
char c = 0;
int p = 0;

void setup() {
// initialize the ethernet device
Ethernet.begin(mac, ip, gateway, subnet);
// start listening for clients
server.begin();

// initialize gpib line
pinMode(EOI, OUTPUT); digitalWrite(EOI, HIGH);
pinMode(DAV, OUTPUT); digitalWrite(DAV, HIGH);
pinMode(NDAC, OUTPUT); digitalWrite(NDAC, LOW);
pinMode(NRFD, OUTPUT); digitalWrite(NRFD, LOW);

}

void loop() {
int i;

Client client = server.available();

if (client) {
while (client.connected()) {
if (0 < client.available()) {
c = client.read();
*(com + p) = c; *(com + p + 1) = 0;
p++;
}

if (';' == c) {
*(com + p - 1) = 0;
if (0 == strcmp("IFC", com)) { gpibIFC();
} else if (0 == strcmp("DCL", com)) { gpibDCL();
} else if (0 == strcmp("STA", com)) { gpibLineStatus();
} else {
char command;
int addr;
char option[255];
sscanf(com, "%c%2d", &command, &addr);
for (i = 4 ; i < strlen(com) ; i++) {
option[i-4] = *(com + i);
} option[i-4] = 0;
strcat(option, "\r\n");

if ('W' == command) {
gpibTalk((byte)addr, option);
} else if ('R' == command) {
char str[255] = "";
gpibListen((byte)addr, str, "\r\n"); server.println(str);
} else if ('C' == command) {
gpibSDC((byte)addr);
}
}
*com = 0; p = 0; c = 0;
}
}
}
}

void gpibLineStatus(void) {
pinMode(ATN, INPUT); digitalWrite(ATN, HIGH); Serial.print(" ATN="); Serial.print(digitalRead(ATN));
pinMode(DAV, INPUT); digitalWrite(DAV, HIGH); Serial.print(", DAV="); Serial.print(digitalRead(DAV));
pinMode(NRFD, INPUT); digitalWrite(NRFD, HIGH); Serial.print(", NRFD="); Serial.print(digitalRead(NRFD));
pinMode(NDAC, INPUT); digitalWrite(NDAC, HIGH); Serial.print(", NDAC="); Serial.print(digitalRead(NDAC));
pinMode(EOI, INPUT); digitalWrite(EOI, HIGH); Serial.print(", EOI="); Serial.print(digitalRead(EOI));
Serial.print(", DIO8-1=");
pinMode(DIO8, INPUT); digitalWrite(DIO8, HIGH); Serial.print(digitalRead(DIO8));
pinMode(DIO7, INPUT); digitalWrite(DIO7, HIGH); Serial.print(digitalRead(DIO7));
pinMode(DIO6, INPUT); digitalWrite(DIO6, HIGH); Serial.print(digitalRead(DIO6));
pinMode(DIO5, INPUT); digitalWrite(DIO5, HIGH); Serial.print(digitalRead(DIO5));
pinMode(DIO4, INPUT); digitalWrite(DIO4, HIGH); Serial.print(digitalRead(DIO4));
pinMode(DIO3, INPUT); digitalWrite(DIO3, HIGH); Serial.print(digitalRead(DIO3));
pinMode(DIO2, INPUT); digitalWrite(DIO2, HIGH); Serial.print(digitalRead(DIO2));
pinMode(DIO1, INPUT); digitalWrite(DIO1, HIGH); Serial.println(digitalRead(DIO1));

}

byte get_dio() {
byte x = 0;

pinMode(DIO1, INPUT); bitWrite(x, 0, !digitalRead(DIO1));
pinMode(DIO2, INPUT); bitWrite(x, 1, !digitalRead(DIO2));
pinMode(DIO3, INPUT); bitWrite(x, 2, !digitalRead(DIO3));
pinMode(DIO4, INPUT); bitWrite(x, 3, !digitalRead(DIO4));
pinMode(DIO5, INPUT); bitWrite(x, 4, !digitalRead(DIO5));
pinMode(DIO6, INPUT); bitWrite(x, 5, !digitalRead(DIO6));
pinMode(DIO7, INPUT); bitWrite(x, 6, !digitalRead(DIO7));
pinMode(DIO8, INPUT); bitWrite(x, 7, !digitalRead(DIO8));

return x;
}

void set_dio(byte x) {

pinMode(DIO1, OUTPUT); digitalWrite(DIO1, bitRead(~x, 0));
pinMode(DIO2, OUTPUT); digitalWrite(DIO2, bitRead(~x, 1));
pinMode(DIO3, OUTPUT); digitalWrite(DIO3, bitRead(~x, 2));
pinMode(DIO4, OUTPUT); digitalWrite(DIO4, bitRead(~x, 3));
pinMode(DIO5, OUTPUT); digitalWrite(DIO5, bitRead(~x, 4));
pinMode(DIO6, OUTPUT); digitalWrite(DIO6, bitRead(~x, 5));
pinMode(DIO7, OUTPUT); digitalWrite(DIO7, bitRead(~x, 6));
pinMode(DIO8, OUTPUT); digitalWrite(DIO8, bitRead(~x, 7));

}

void gpibWrite(byte data) {
// wait until (LOW == NDAC)
pinMode(NDAC, INPUT);
while (HIGH == digitalRead(NDAC)) { ; }

// output data to DIO
set_dio(data);

// wait until (HIGH == NRFD)
pinMode(NRFD, INPUT);
while (LOW == digitalRead(NRFD)) { ; }

// validate data
pinMode(DAV, OUTPUT);
digitalWrite(DAV, LOW);

// wait until (HIGH == NDAC)
while (LOW == digitalRead(NDAC)) { ; }

digitalWrite(DAV, HIGH);
set_dio(0); delayMicroseconds(10);

return;
}

boolean gpibRead(byte *data) {

boolean ret = false;

// prepare to listen
pinMode(NRFD, OUTPUT);
digitalWrite(NRFD, HIGH);

// wait until (LOW == DAV)
pinMode(DAV, INPUT);
while (HIGH == digitalRead(DAV)) { ; }

// Ready for data
digitalWrite(NRFD, LOW);

// read from DIO
*data = get_dio();

// check EOI
pinMode(EOI, INPUT);
if (LOW == digitalRead(EOI)) {
ret = true;
} else {
ret = false;
}

// data accepted
pinMode(NDAC, OUTPUT);
digitalWrite(NDAC, HIGH);

// wait until invalid data
while (LOW == digitalRead(DAV)) { ; }
digitalWrite(NDAC, LOW);

return ret; // return true when EOI==LOW
}

void gpibTalk(byte addr, char *str) {
// attention
pinMode(EOI, OUTPUT);
digitalWrite(EOI, HIGH);
pinMode(ATN, OUTPUT);
digitalWrite(ATN, LOW); delayMicroseconds(30);

// unlisten
gpibWrite(0x3F); delayMicroseconds(20);

// talker address
gpibWrite(0x40); delayMicroseconds(20);

// listener address
gpibWrite((byte)(0x20 + addr)); delayMicroseconds(20);

// end of attention
digitalWrite(ATN, HIGH); delayMicroseconds(20);

// write string
while (0 != *(str + 1)) {
gpibWrite(*str); delayMicroseconds(20);
str++;
}

// write last char
digitalWrite(EOI, LOW);
gpibWrite(*str); delayMicroseconds(20);
digitalWrite(EOI, HIGH);

}

boolean gpibListen(byte addr, char *str, char* del) {
// attention
pinMode(ATN, OUTPUT);
digitalWrite(ATN, LOW); delayMicroseconds(30);

// unlisten
gpibWrite(0x3F); delayMicroseconds(20);

// talker address
gpibWrite((byte)(0x40 + addr)); delayMicroseconds(20);

// listener address
gpibWrite(0x20); delayMicroseconds(20);

// end of attention
pinMode(NRFD, OUTPUT); digitalWrite(NRFD, LOW);
pinMode(NDAC, OUTPUT); digitalWrite(NDAC, LOW);

delayMicroseconds(10);
digitalWrite(ATN, HIGH); delayMicroseconds(20);

// recieve data
int i, s, len = strlen(del);
byte c;
boolean isLast, isDel;

s = 0;
do {
isLast = gpibRead(&c); *(str) = c;
isDel = true;
for (i = 0 ; i < len ; i++) {
isDel = isDel & (*(str - i) == *(del + len - i - 1));
}
str++;
} while (!(isLast || isDel));
*(str) = 0;

return true;
}

void gpibIFC(void) {
pinMode(IFC, OUTPUT); digitalWrite(IFC,LOW); delayMicroseconds(128);
digitalWrite(IFC, HIGH);
}

void gpibDCL(void) {
// attention
pinMode(ATN, OUTPUT); digitalWrite(ATN, LOW); delayMicroseconds(10);

// send DCL
gpibWrite(0x14); delayMicroseconds(10);

// end of attention
digitalWrite(ATN, HIGH); delayMicroseconds(20);
}

void gpibSDC(byte addr) {
// attention
pinMode(ATN, OUTPUT); digitalWrite(ATN, LOW); delayMicroseconds(10);

// unlisten
gpibWrite(0x3F); delayMicroseconds(10);

// send ADDRESS for device clear
gpibWrite((byte)(32 + addr)); delayMicroseconds(10);

// send SDC
gpibWrite(0x04); delayMicroseconds(10);

// end of attention
digitalWrite(ATN, HIGH); delayMicroseconds(20);
}
 
CircuitGizmos

Guru

Joined: 08/09/2011
Location: United States
Posts: 1416
Posted: 08:29am 05 Jan 2013
Copy link to clipboard 
Print this post

So I would suppose if you change the Arduino code to be serial to GPIB, then you could mount an Arduino onto a ColorMax as if it were a shield. Extend the power and serial pins below the Arduino to mount the Arduino as if it were a shield. Snap a proto-shield on top of the Arduino that has the GPIB connector wired in place.

MMBasic could control this through serial commands.
Micromites and Maximites! - Beginning Maximite
 
boss

Senior Member

Joined: 19/08/2011
Location: Canada
Posts: 268
Posted: 08:46am 05 Jan 2013
Copy link to clipboard 
Print this post

Greeting fro Vancouver,

yes that's exactly what I'm thinking about. The next step should be to MM/CMM as the control unit. This design is good for testing purposes or work with just one "listener" because MM I/O cannot follow full GPIB electrical specification.

Regards
boss
 
CircuitGizmos

Guru

Joined: 08/09/2011
Location: United States
Posts: 1416
Posted: 09:06am 05 Jan 2013
Copy link to clipboard 
Print this post

Someone ambitious could always pull the "arduino code" into an appropriate AVR and design a GPIB shield.
Micromites and Maximites! - Beginning Maximite
 
boss

Senior Member

Joined: 19/08/2011
Location: Canada
Posts: 268
Posted: 10:43am 05 Jan 2013
Copy link to clipboard 
Print this post

Hi,

absolutely, the there is just necessary to conditioned the cpu signals using the noniverting GPIB transceivers ie. DS75160/161/162 and that's it.

I have couple of equipments I would like to control via GBIB bus.

Regards
boss
 
boss

Senior Member

Joined: 19/08/2011
Location: Canada
Posts: 268
Posted: 07:21pm 09 Jan 2013
Copy link to clipboard 
Print this post

Hi,

another $5 GPIB solution including BASIC source code. You can download trial version BASCOM compiler(code limit 4kB which is more then enough)



'*********************************************************** *******************
' (c) Jan Petersen
' Orevej 6
' DK 4760 Vordingborg
' jan_p@post8.tele.dk
'----------------------------------------------------------- -------------------
' Date: 24.02.2000
' Compiler: Bascom AVR 1.0.8b
' File: Serial2Gpib.bas
' Description: RS232 to GPIB converter +
' HPGL to GDU converter
'
' This program is made specific for my Tektronix 4662 flatbed plotter
' with GPIB (IEE488) interface, and a strange GDU coordinate system..!
' Now it communicate whit a HPGL device-driver trough a normal
' RS 232 serialport. Hey man...
'----------------------------------------------------------- -------------------
'
' Input:
' RS232 :19200N81R
' Handshake :RTS/CTS specific for (Eagle CAM processor)
'
' Output:
' GPIB :DATA[0..7] (Inverted !Activ Low!)
' Handshake :DAV (DataValid)
' Handshake :NDAC (NoDataAccepted)
' Handshake :NRFD (NotReadyForData)
'----------------------------------------------------------- -------------------
'
' HPGL commands: Tektronix 4662 Plotter Commands:
' PU; (PenUp) M[cr]
' PD; (PenDown) D[cr]
' PA xxx,yyy; (PlotAbsolut) Dxxx,yyy[cr]
' VS xx; (VelocitySpeed) BYxx[cr]
' SP 0; (SelectPen) End Of File so goto home = M150,100[cr]
'
' GDU = GraphicDataUnit
' HPGL = HeweletPackardGraphicLanguage
'
' 1 GDU = 2.54 mm
' 1 HPGL unit = 0.025 mm
'
' 100 HPGL units = 1 GDU
' 1 HPGL units = 0.01 GDU
'
' All coordinates are divided by 100
'
' A typical input format would look like this (Eagle Cam processor-HPGL driver)
'
' IN; IP 0,0,100,100; SC 0,100,0,100;
' VS 120
' SP 2;
' PU;
' PA 19,18;
' PD;
' PA 1035,18;
' PU; SP 0; PA 0,0;
'
' Converted output to Tektronix plotter
'
' BY120
' M0.19,0.18
' D10.35,0.18
' M150.100
'*********************************************************** *******************

$regfile = "2313def.dat"
$crystal = 7372800 '7.372800 MHz crystal
$baud = 19200 '@ 19.2 Kbaud error is 0.0%

Dim Result As String * 15
Dim Value_x As String * 7
Dim Value_y As String * 7
Dim Low_ As String * 2
Dim High_ As String * 3
Dim Command As String * 1
Dim A As Byte , B As Byte
Dim H As Byte , L As Byte , Data_inv As Byte

' Init ports ---------------------------------------
Ddrd = &B00010100
Config Portb = Output

Data_out Alias Portb 'Data byte to GPIB PortB
'RX PortD.0
'TX PortD.1
Rts_cts Alias Portd.2 'RTS/CTS handshake PortD.2
Dav Alias Portd.4 'DAV PortD.4
'NDAC PortD.5
'NRFD PortD.6

' Start --------------------------------------------
set dav 'No DataValid on GPIB port
Command = "M" 'set Command to MOVE
Gosub _reset 'reset variable
Reset Rts_cts 'uP ready

' Main loop ----------------------------------------
Do
A = Waitkey() 'wait for a character
set Rts_cts 'uP NOT ready

Select Case A
Case 10 : Gosub _reset 'linefeed
Case 13 : Gosub _reset 'carriage return
Case 32 : Gosub _space 'space
Case 44 : Gosub _comma 'comma
Case 59 : Gosub _semicolon 'semicolon
Case Else : Result = Result + Chr(a) 'add the character to string
End Select

Reset Rts_cts 'uP ready
Loop


_space:
' SPACE
'***************************************************
Select Case Result
Case "VS" : Command = "V" 'VelocitySpeed
Case "SP" : Command = "S" 'SelectPen
Case "PU" : Command = "M" 'PenUp
Case "PD" : Command = "D" 'PenDown
End Select

Gosub _reset
Return


_comma:
' COMMA
'***************************************************
Value_x = Result 'value_x = X-coordinate
Result = "" 'clear Result
Return


_semicolon:
' SEMICOLON
'***************************************************
Select Case Command
Case "V" : Gosub _vs 'Velocity
Case "S" : Gosub _sp 'Select Pen
Case "R" : Gosub _reset '/Dummy Chr...!
End Select '/SP 0 command was detected
'/in the _sp SUB
'/means ..EOF..
Select Case Result
Case "PU" : Command = "M" 'Move
Case "PD" : Command = "D" 'Draw
Case Else : Gosub _make_string 'value_y is in result
End Select

Gosub _reset
Return


_vs:
' PEN SPEED (velocity speed)
'***************************************************
If Result <> "0" Then
Result = "BY" + Result + Chr(13)
Gosub _gpib_out 'BYxx[cr]
End If

Gosub _reset : Command = "M"
Return


_sp:
' SELECT PEN
' if a "SP 0" command is recived
' it means "MOVE HOME" and EOF
'***************************************************
If Result = "0" Then
Result = "M150," + "100" + Chr(13)
Gosub _gpib_out 'M150,100[cr]
Command = "R" '/R means EOF
'/and is at dummy Chr
'/used in _semicolon SUB
Else
Command = "M"
End If

Gosub _reset
Return


_make_string:
' Prepare the string to send to GPIB
'***************************************************
If Result = "" Then Return

If Value_x = "" Then
Gosub _reset '/happens on the first line
Return '/when value_x is NUL
End If

Gosub _divide 'value_Y is in result
Value_y = Result 'value_Y = value_y / 100

Result = Value_x 'now value_X is in result

Gosub _divide
Value_x = Result 'value_X = value_x / 100

' Assemble the string -----------------------------
Result = Command + Value_x + "," + Value_y + Chr(13)

Gosub _gpib_out 'eg.Result = "M12.78,56[cr]"
Gosub _reset
Return


_reset:
' Reset some variable
' This SUB saves lot of ROM Space.. :o)
'***************************************************
Result = "" 'saves some program memory
Value_x = "" 'when variables are cleared
Value_y = "" 'in one SUB
Return


_divide:
' divide by 100
' SINGLE aritmic don't work yet, so we do It like this..!
'***************************************************
High_ = "" : Low_ = ""

If Result = "0" Then Return 'don't divide, value is zero

L = Len(result) 'length of string

If L > 2 Then H = L - 2

If L = 1 Then Low_ = Right(result , 1) '1'st decimal value
If L > 1 Then Low_ = Right(result , 2) '2'nd decimal value
If L > 2 Then High_ = Mid(result , 1 , H) 'real value

If L = 1 Then Result = "0.0" + Low_ '1 decimal
If L = 2 Then Result = "0." + Low_ '2 decimal
If L > 2 Then Result = High_ + "." + Low_ 'real + decimal

B = Val(low_)
If B = 0 Then Result = High_ 'ONLY real
Return


_gpib_out:
' Output data to GPIB port
' Data is inverted
' NRFS,NDAC and DAV is handshake
'***************************************************
L = Len(result) 'how long is the string..?

For H = 1 To L 'loop the string
Low_ = "" 're use a old variable

Low_ = Mid(result , H , 1) 'pick out the character
Data_inv = 255 - Asc(low_) 'invert the character

Bitwait Pind.6 , Set 'wait until (NRFD) goes HIGH

Data_out = Data_inv 'Set the data on the port

Reset Dav 'DataValid on port

Bitwait Portd.6 , Reset 'wait until (NRFD) goes LOW

Bitwait Pind.5 , Set 'wait until (NDAC) goes HIGH

set dav 'Data NOT Valid on port

Bitwait Portd.5 , Reset 'wait until (NDAC) goes LOW
Next H

Bitwait Pind.6 , Set 'wait until (NRFD) goes HIGH
Return

End
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2022