I wrote a python code (raspberry pi) to receive voltage, current and power values from ATM90E32AS energy meter IC. Iam using spidev library for SPI communication with the energy meter IC. I initialized two bytearrays (each 4 bytes wide) for reading and writing the energy meter IC like
writeBuffer = bytearray ([0x00,0x00,0x00,0x00])
readBuffer = bytearray ([0x00,0x00,0x00,0x00])
For example reading active R phase voltage i initialized the register values like
VrRead_Reg = bytearray ([0x80, 0xD9])
And i try to write the above value to the IC using following subroutine to read the R phase voltage
def Vr_read():
writeBuffer[0] = VrRead_Reg[0]
writeBuffer[1] = VrRead_Reg[1]
#print(writeBuffer)
readBuffer = spi.xfer(writeBuffer)
print("Vr:",readBuffer)
time.sleep(0.5)
And iam getting the output like
Vr: [255,255,89,64]
Vr: [255,255,89,170]
Vr: [255,255,89,220]
Vr: [255,255,89,1]
Vr: [255,255,89,10]
I measured the voltage at mains it shows 230V. Then i try to match the above output with the measured voltage. Here the third byte 89 corresponds to 230V. Then i used a variac to change the voltage this time for 220V the third byte value becomes 85 and for 210V its 81 and for 100V it was 39 and so on.
I don't know how to relate 89 with 230V and also about other bytes. Plz help to decode the above output.
Do some ratio calculation:
(consider the max value of a byte is 255)
255 / 89 * 230 = 658.99 (approximately 660V)
85 / 255 * 660 = 220(220V)
81 / 255 * 660 = 209.65(210V)
39 / 255 * 660 = 100.94(100V)
But you had better find the device manual to get reference.
Related
I'm using python to read in values from a high-speed 8-bit ADC (the ADS7885 linked here) and convert them into voltages using the SPI0 ports on a Raspberry Pi 4. At this point, I do receive values from the ADC on the Raspberry Pi, but the values I am reading in are not at all accurate. I was hoping someone might be able to help me out with my code so that I can accurately read values from the ADC at a sampling rate of 48mHz and convert them into voltages?
I think the problem might have to do with the number of clock cycles it takes before the ADC can read/convert valid data? The datasheet says that this specific ADC requires 16 SCLK cycles before it is able to begin converting valid data, but I'm not sure how to enforce this in my code.
I followed sample code for a 10-bit ADC that uses the Spidev python module, but I'm open to any other code solutions. This is what I'm currently running:
spi404 = spidev.SpiDev(0, 0)
def read_adc404(adc_ch, vref = 5):
msg = 0b11
msg = ((msg << 1) + 0) << 3
msg = (msg, 0b000000)
reply = spi404.xfer2(msg)
adc = 0
for n in reply:
adc = (adc << 6) + n
adc = adc >> 2
voltage = (vref * adc) / 256
return voltage
Any tips or help would be greatly appreciated!!
my very first post - so please be gentle
Raspberry Pi Zero - Python3, AD5325 10 bit DAC
I realise I'm probably biting off more than I can chew for such a python beginner - but I do have some basic programing experience and there is nothing like trying to make something real actually work. What I'm trying to do is convert my working 'basic' uC code to Python for use on the Pi
This is the working code in basic
W_Data_DAC=W_Data_DAC*3.41 'value between 0 and 300 - scaled to 10 bits
Clear B_DAC_pnt 'clear the pointer
B_DAC_pnt.2=1 'set for DAC C
W_Data_DAC=W_Data_DAC<<2 'shift left 2 places (to fit the DAC requirements)
W_Data_DAC.12=0 'set to update all channels
W_Data_DAC.13=1 'Normal Operation
BusOut Ad5315,[B_DAC_pnt,B_Hi_DAC,B_Lo_DAC] 'update each DAC
So I start of with a word size variable between 0 - 1023 (10 bits) W_Data_DAC
set bit 2 of a pointer byte (B_DAC_pnt) - instruct to write to ch C
shift W_Data_DAC left 2 places
clear W_Data_DAC bit 12 - instruct to update all ch
set W_Data_DAC bit 13 - instruct normal operation
then write 3 bytes to the DAC via the i2c bus
This is the code I have so far in Python
import smbus
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM) # GPIO Numbers instead of board numbers
#GPIO.setwarning(False) # no warnings
Coil_1 = 17
Coil_2 = 27
Coil_3 = 22
chan_list = [Coil_1,Coil_2,Coil_3]
GPIO.setup(chan_list, GPIO.OUT)
#GPIO.setup(Coil_1, GPIO.OUT) # GPIO Assign mode
#GPIO.setup(Coil_2, GPIO.OUT) # GPIO Assign mode
#GPIO.setup(Coil_3, GPIO.OUT) # GPIO Assign mode
bus = smbus.SMBus(1)
adc_add=0x4d #ADC address
dac=0x0c #DAC address
def an_in(): #read the current analogue input
result=bus.read_i2c_block_data(adc_add, 0x00, 2)
test1=(result[0]<<8)+result[1]
v_in=test1*0.001221
return v_in
def an_out(v_out): #v_out will be a value 0 to 300 from the calling routine)
v_out=v_out*3.41 #range now 0-1023 10 bits
#convert this a 16 bit word
W_Out=int(v_out) # convert to an integer (? 16 bits)
W_out=W_out<<2 #shift left 2 places
W_out=W_out | 12288 #Logocal OR to set bit 13
bus.write_i2c_block_data(dac,W_out)
while True:
#run through the relays
GPIO.output(Coil_1, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(Coil_1, GPIO.LOW)
time.sleep(0.5)
GPIO.output(Coil_2, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(Coil_2, GPIO.LOW)
time.sleep(0.5)
GPIO.output(Coil_3, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(Coil_3, GPIO.LOW)
time.sleep(0.5)
#This reads the state of the PCF8574 Port Expander / anlg input
result=bus.read_byte(0x20)
print('Dig Input ',format(result,'08b'))
print('Anlg In = ',format(an_in(),'f'))
an_out(an_in) #call the DAC value 0-300
time.sleep(2)
as you can see - I have 3 relays, 1 ADC and a DAC - ok with the first 2 parts, but a bit stumped with the DAC.
The output I'm getting is:
Dig Input 11111111
Anlg In = 3.632475
Traceback (most recent call last):
File "i2c.py", line 67, in
an_out(an_in) #call the DAC value 0-300
File "i2c.py", line 34, in an_out
v_out=v_out*3.41 #range now 0-1023 10 bits
TypeError: unsupported operand type(s) for *: 'function' and 'float'
I suspect I'm making a number of very basic errors here - but my approach to learning is 'bite off more than you can chew - then chew like mad'
Specifically my questions are - why I can't call the function an_out(an_in)?
and why can't I multiply the variable v_out by 4.31 - I haven't specified the var as an integer anywhere?
Also - I suspect this is not the correct way to write to the DAC in this case anyway?
This question is as much me 'dipping my toe' as it it trying to solve a particular problem - my next challenge is figuring out my toolchain (vim seems very clunky - I'm after an IDE that works headlessly and has a good debugger - I get a lot of bugs :-)
Any help or advice would be much appreciated. Thanks
Resolved - posted here for future reference
import smbus
def an_out(v_out): #0 to 300 (PSI)
if v_out > 300:
v_out = 300 #max value is 300
print('Anlg Out = ', v_out)
v_out = int(v_out * 3.41) #scale to 10 bits
v_out = v_out << 2 #shift left 2 places
mask = 1 << 13 #set mask
v_out = v_out | mask #this should set bit 13
v_out_hi = v_out & 65280 #mask out the high byte
v_out_hi = v_out_hi >> 8 #shiift down to 8 bits
v_out_lo = v_out & 255 #mask out the high byte
b_pnt=1 #DAC Ch C
command = [(v_out_hi), (v_out_lo)] #load the command
bus.write_i2c_block_data(dac, b_pnt, command) #i2c (4-20ma out)
b_pnt=4 #DAC Ch A
bus.write_i2c_block_data(dac, b_pnt, command) #i2c (0-10v out)
I'd be glad if anyone can advise if I have approached this incorrectly or my coding style is not up to scratch (only just starting with python).
Kind regards
I really need your help because I'm trying to solve this for some time now but cannot get it done!
We have a Davis Weather Station with the WeatherLink Software. This is downloading all weatherdata from the station and saving it to a yyyy-mm.wlk File.
I would like to visualize it within PowerBI but the wlk Files seem to be saved in a binary encoded kind.
So I started programming with python to convert it anyhow to a csv file. I eaven found a Java based solution here: Java Program WLK Reader
I tried to use this code and make it running in python but nothing worked. Does anyone have an idea how I can convert these files?
So far I tried this:
#from PyByteBuffer import ByteBuffer #https://pypi.org/project/PyByteBuffer/
import struct
in_file = open(r"D:\Temp\WeatherStation\2013-08.wlk", "rb")
data = in_file.read()
in_file.close()
#content = data.decode('ansi').splitlines()
content = data.decode('ansi', 'slashescape')
#offset = 0
#content = struct.unpack_from("<L", data, offset)
with open(r"D:\Temp\WeatherStation\Output.txt", "w") as text_file:
for line in content:
text_file.write(line)
#decoded = data.decode('ansi', 'slashescape')
#offset = 0
#content = struct.unpack_from("<d", data, offset)
#data.decode('ansi', 'slashescape')
I'm comletely lost with this and have no idea what I can do to get this done and hope that maybe someone of you can help me...
As soon as I get it done I'll post the code here so everybody can use it within PowerBI to visulize it more nicely than within WeatherLink :-)
You can find example files right here: Example Files
Thank you very much!
Victor
Here comes the detailed File Description from the Readme as Ronald mentioned:
Data File Structure
What follows is a technical description of the .WLK weather database
files. This is of interest mostly to programmers who want to write
their own programs to read the data files.
The data filename has the following format: YYYY-MM.wlk where YYYY is
the four digit year and MM is the two digit month of the data
contained in the file.
The structures defined below assume that no bytes are added to the
structures to make the fields are on the "correct" address boundaries.
With the Microsoft C++ compiler, you can use the directive "#pragma
pack (1)" to enforce this and use "#pragma pack ()" to return the
compiler to its default behavior.
// Data is stored in monthly files. Each file has the following
header. struct DayIndex { short recordsInDay; // includes any
daily summary records long startPos; // The index (starting at
0) of the first daily summary record };
// Header for each monthly file. // The first 16 bytes are used to
identify a weather database file and to identify // different file
formats. (Used for converting older database files.) class HeaderBlock
{ char idCode [16]; // = {'W', 'D', 'A', 'T', '5', '.', '0', 0, 0,
0, 0, 0, 0, 0, 5, 0} long totalRecords; DayIndex dayIndex [32];
// index records for each day. Index 0 is not used
// (i.e. the 1'st is at index 1, not index 0) };
// After the Header are a series of 88 byte data records with one of
the following // formats. Note that each day will begin with 2
daily summary records
// Daily Summary Record 1 struct DailySummary1 { BYTE dataType = 2;
BYTE reserved; // this will cause the rest of the fields to start
on an even address
short dataSpan; // total # of minutes accounted for by physical
records for this day short hiOutTemp, lowOutTemp; // tenths of a
degree F short hiInTemp, lowInTemp; // tenths of a degree F
short avgOutTemp, avgInTemp; // tenths of a degree F (integrated over
the day) short hiChill, lowChill; // tenths of a degree F
short hiDew, lowDew; // tenths of a degree F short
avgChill, avgDew; // tenths of a degree F short hiOutHum,
lowOutHum; // tenths of a percent short hiInHum, lowInHum; //
tenths of a percent short avgOutHum; // tenths of a
percent short hiBar, lowBar; // thousandths of an inch Hg
short avgBar; // thousandths of an inch Hg short
hiSpeed, avgSpeed; // tenths of an MPH short dailyWindRunTotal;
// 1/10'th of an mile short hi10MinSpeed; // the highest
average wind speed record BYTE dirHiSpeed, hi10MinDir; //
direction code (0-15, 255) short dailyRainTotal; //
1/1000'th of an inch short hiRainRate; // 1/100'th
inch/hr ??? short dailyUVDose; // 1/10'th of a standard
MED BYTE hiUV; // tenth of a UV Index BYTE
timeValues[27]; // space for 18 time values (see below) };
// Daily Summary Record 2 struct DailySummary2 { BYTE dataType = 3;
BYTE reserved; // this will cause the rest of the fields to start
on an even address
// this field is not used now. unsigned short todaysWeather; //
bitmapped weather conditions (Fog, T-Storm, hurricane, etc)
short numWindPackets; // # of valid packets containing wind
data,
// this is used to indicate reception quality short hiSolar; // Watts per meter squared
short dailySolarEnergy; // 1/10'th Ly short minSunlight;
// number of accumulated minutes where the avg solar rad > 150
short dailyETTotal; // 1/1000'th of an inch short hiHeat,
lowHeat; // tenths of a degree F short avgHeat; //
tenths of a degree F short hiTHSW, lowTHSW; // tenths of a
degree F short hiTHW, lowTHW; // tenths of a degree F
short integratedHeatDD65; // integrated Heating Degree Days (65F
threshold)
// tenths of a degree F - Day
// Wet bulb values are not calculated short hiWetBulb,
lowWetBulb; // tenths of a degree F short avgWetBulb; //
tenths of a degree F
BYTE dirBins[24]; // space for 16 direction bins
// (Used to calculate monthly dominant Dir)
BYTE timeValues[15]; // space for 10 time values (see below)
short integratedCoolDD65; // integrated Cooling Degree Days (65F
threshold)
// tenths of a degree F - Day BYTE reserved2[11]; };
// standard archive record struct WeatherDataRecord { BYTE dataType
= 1; BYTE archiveInterval; // number of minutes in the archive // see below for more details about these next two fields) BYTE
iconFlags; // Icon associated with this record, plus Edit
flags BYTE moreFlags; // Tx Id, etc.
short packedTime; // minutes past midnight of the end of
the archive period short outsideTemp; // tenths of a degree
F short hiOutsideTemp; // tenths of a degree F short
lowOutsideTemp; // tenths of a degree F short insideTemp;
// tenths of a degree F short barometer; // thousandths
of an inch Hg short outsideHum; // tenths of a percent
short insideHum; // tenths of a percent unsigned short
rain; // number of clicks + rain collector type code short
hiRainRate; // clicks per hour short windSpeed;
// tenths of an MPH short hiWindSpeed; // tenths of an MPH
BYTE windDirection; // direction code (0-15, 255) BYTE
hiWindDirection; // direction code (0-15, 255) short
numWindSamples; // number of valid ISS packets containing wind
data
// this is a good indication of reception short solarRad, hisolarRad;// Watts per meter squared
BYTE UV, hiUV; // tenth of a UV Index
BYTE leafTemp[4]; // (whole degrees F) + 90
short extraRad; // used to calculate extra heating
effects of the sun in THSW index
short newSensors[6]; // reserved for future use BYTE forecast; // forecast code during the archive interval
BYTE ET; // in thousandths of an inch
BYTE soilTemp[6]; // (whole degrees F) + 90 BYTE soilMoisture[6]; // centibars of dryness BYTE leafWetness[4];
// Leaf Wetness code (0-15, 255) BYTE extraTemp[7]; //
(whole degrees F) + 90 BYTE extraHum[7]; // whole percent
};
Notes:
Always check the dataType field to make sure you are reading the
correct record type
There are extra fields that are not used by the current software. For
example, there is space for 7 extra temperatures and Hums, but current
Vantage stations only log data for 3 extra temps and 2 extra hums.
Extra/Soil/Leaf temperatures are in whole degrees with a 90 degree
offset. A database value of 0 = -90 F, 100 = 10 F, etc.
The rain collector type is encoded in the most significant nibble of
the rain field. rainCollectorType = (rainCode & 0xF000); rainClicks =
(rainCode & 0x0FFF);
Type rainCollectorType
0.1 inch 0x0000
0.01 inch 0x1000
0.2 mm 0x2000
1.0 mm 0x3000
0.1 mm 0x6000 (not fully supported)
Use the rainCollectorType to interpret the hiRainRate field. For
example, if you have a 0.01 in rain collector, a rain rate value of
19 = 0.19 in/hr = 4.8 mm/hr, but if you have a 0.2 mm rain collector,
a rain rate value of 19 = 3.8 mm/hr = 0.15 in/hr.
Format for the iconFlags field The lower nibble will hold a value that
will represent an Icon to associate with this data record (i.e. snow,
rain, sun, lightning, etc.). This field is not used.
Bit (0x10) is set if the user has used the edit record function to
change a data value. This allows tracking of edited data.
Bit (0x20) is set if there is a data note associated with the archive
record. If there is, it will be found in a text file named
YYYYMMDDmmmm.NOTE. YYYY is the four digit year, MM is the two digit
month (i.e. Jan = 01), DD is the two digit day, and mmmm is the number
of minutes past midnight (i.e. the packedTime field). This file is
found in the DATANOTE subdirectory of the station directory.
Format for the moreFlags field The lowest 3 bits contain the
transmitter ID that is the source of the wind speed packets recorded
in the numWindSamples field. This value is between 0 and 7. If your
ISS is on ID 1, zero will be stored in this field.
WindTxID = (moreFlags & 0x07);
Time values and Wind direction values in Daily Summary records These
values are between 0 and 1440 and therefore will fit in 1 1/2 bytes,
and 2 values fit in 3 bytes. Use this code to extract the i'th time or
direction value. See below for the list of i values.
fieldIndex = (i/2) * 3; // note this is integer division (rounded
down)
if (i is even) value = field[fieldIndex] + (field[fieldIndex+2] &
0x0F)<<8;
if (i is odd) value = field[fieldIndex+1] +
(field[fieldIndex+2] & 0xF0)<<4;
A value of 0x0FFF or 0x07FF indicates no data available (i.e. invalid
data)
The time value represents the number of minutes after midnight that
the specified event took place (actually the time of the archive
record).
The wind direction bins represent the number of minutes that that
direction was the dominant wind direction for the day.
Index values for Daily Summary Record 1 time values Time of High
Outside Temperature 0 Time of Low Outside Temperature 1 Time of
High Inside Temperature 2 Time of Low Inside Temperature 3 Time
of High Wind Chill 4 Time of Low Wind Chill 5
Time of High Dew Point 6 Time of Low Dew Point
7 Time of High Outside Humidity 8 Time of Low Outside Humidity
9 Time of High Inside Humidity 10 Time of Low Inside Humidity
11 Time of High Barometer 12 Time of Low Barometer
13 Time of High Wind Speed 14 Time of High Average Wind
Speed 15 Time of High Rain Rate 16 Time of High UV
17
Index values for Daily Summary Record 2 time values Time of High
Solar Rad 0 Time of High Outside Heat Index 1 Time of
Low Outside Heat Index 2 Time of High Outside THSW Index 3 Time
of Low Outside THSW Index 4 Time of High Outside THW Index 5
Time of Low Outside THW Index 6 Time of High Outside Wet Bulb
Temp 7 Time of Low Outside Wet Bulb Temp 8 (Time value 9 is not used)
Index values for Dominant Wind direction bins in Daily Summary Record
2 N 0 NNE 1 NE 2 ... NW 14 NNW 15
I'm trying to read the temperature and humidity using a Texas Instruments HDC1008 from Adafruit, product 2635. I'm on a rasberry pi 2, using the smbus module. According to TI's PDF, when getting a reading, the number will be sent in two bytes that you put together. I found this code that does what I'm trying to do with micropython, where they have a recv function that seems to simply sends them back a list with two bytes. The SMBus module doesn't seem to have any equivalent for what I'm trying to do. Here's some of my code.
class HDC1008:
I2C_BUS = 1
#Registers
REG_TEMP = 0
REG_HUMID = 1
REG_CONFIG = 2
#Configuration bits
CFG_RST = 1<<15
CFG_MODE_SINGLE = 0 << 12
CFG_MODE_BOTH = 1 << 12
ADDRESS = 0x40
def __init__(self, bus_num=I2C_BUS):
self.bus=smbus.SMBus(bus_num)
def readTemperature(self):
#configure the HDC1008 for one reading
config = 0
config |= self.CFG_MODE_SINGLE
self.bus.write_byte_data(self.ADDRESS, self.REG_CONFIG, config)
#tell the thing to take a reading
self.bus.write_byte(self.ADDRESS, self.REG_TEMP)
time.sleep(0.015)
#get the reading back from the thing
raw = self.bus.read_byte(self.ADDRESS)
raw = (raw<<8) + self.bus.read_byte(self.ADDRESS)
#use TI's formula to turn it into people numbers
temperature = (raw/65536.0)*165.0 - 40
#convert temp to f
temperature = temperature * (9.0/5.0) + 32
return temperature
When I'm getting the value for raw from bus.read_byte, I'm able to get the first half of the temperature bits, but the second reading is just zeros, presumably because the first transaction is over. How do I get two bytes in one transaction?
tnx a lot for sharing this code. I'm happy to get it working in Python.
I do not exactly understand the problem, I can read the Temperature and Humidity with our code (the only Python code I could find and works)
I did change it a little bit (make it a Class):
import smbus
class HDC:
#Registers
REG_TEMP = 0
REG_HUMID = 1
REG_CONFIG = 2
I2C_BUS = 2 #2 for PCDuino, 1 for PI
#Configuration bits
CFG_RST = 1<<15
CFG_MODE_SINGLE = 0 << 12
CFG_MODE_BOTH = 1 << 12
ADDRESS = 0x40
def __init__(self, bus_num=I2C_BUS):
self.bus=smbus.SMBus(bus_num)
def readTemperature(self):
#configure the HDC1008 for one reading
config = 0
config |= self.CFG_MODE_SINGLE
self.bus.write_byte_data(self.ADDRESS, self.REG_CONFIG, config)
#tell the thing to take a reading
self.bus.write_byte(self.ADDRESS, self.REG_TEMP)
time.sleep(0.015)
#get the reading back from the thing
raw = self.bus.read_byte(self.ADDRESS)
raw = (raw<<8) + self.bus.read_byte(self.ADDRESS)
#use TI's formula to turn it into people numbers
temperature = (raw/65536.0)* 165 - 40
#convert temp to farenheid
#temperature = temperature * (9.0/5.0) + 32
return temperature
def readHum(self):
#configure the HDC1008 for one reading
config = 0
config |= self.CFG_MODE_SINGLE
self.bus.write_byte_data(self.ADDRESS, self.REG_CONFIG, config)
#tell the thing to take a reading
self.bus.write_byte(self.ADDRESS, self.REG_HUMID)
time.sleep(0.015)
#get the reading back from the thing
raw = self.bus.read_byte(self.ADDRESS)
raw = (raw<<8) + self.bus.read_byte(self.ADDRESS)
hum=(raw/(2.0**16))*100
return hum
In the program:
from hdc1008 import HDC
HDC1008=HDC()
print HDC1008.readTemperature()
print HDC1008.readHum()
I am trying to create a prototype to print bitmap data for a text file to my LAN enabled epson pos printer TM-T88V.
While I have no problems to send text and text formatting instructions, I dont understand, what I have to do, to make my printer print the data of the Arecibo message.
first few lines:
00000010101010000000000
00101000001010000000100
10001000100010010110010
10101010101010100100100
00000000000000000000000
00000000000011000000000
00000000001101000000000
00000000001101000000000
00000000010101000000000
00000000011111000000000
00000000000000000000000
11000011100011000011000
10000000000000110010000
11010001100011000011010
11111011111011111011111
00000000000000000000000
00010000000000000000010
00000000000000000000000
00001000000000000000001
The message has 73 rows and 23 columns resulting in 1679 picture elements. Each of this elements is defined by either a 1 for black or a 0 as white and should be printed as a square of 8x8 (or 16x16) dots. the result would result in
(source: satsig.net)
From the printer's specifications:
While — as I said — the connecting and sending to the printer is no problem, I just dont get, what this instruction want to tell me. What would in the case of the Arecibo message be
What numbers do I have to send to the printer? Do I need to send every dot? What does nL, nH specify the number of dots of the image data in the horizontal direction as (nL + nH × 256). mean?
Here is my simple Python program I use for prototyping:
# -*- coding: utf-8 -*-
import struct
import socket
def sendInstructions(mySocket,l):
for x in l:
mySocket.send(struct.pack('h', *[x]),1)
def emphasizeOn(mySocket):
sendInstructions(mySocket,[27,33,48])
def emphasizeOff(mySocket):
sendInstructions(mySocket,[27,33,0])
def lineFeed(mySocket,number):
for i in range(number):
sendInstructions(mySocket,[0x0a,])
def paperCut(mySocket):
sendInstructions(mySocket,[29,86,0])
def sendText(mySocket,string):
mySocket.send(string.encode('UTF-8'))
def main():
mySocket = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
mySocket.connect(('192.168.1.15',9100))
lines = ["Hello,","World!"]
emphasizeOff(mySocket)
lineFeed(mySocket,2)
for l in lines:
if lines.index(l) == 0:
emphasizeOn(mySocket)
else:
emphasizeOff(mySocket)
sendText(mySocket,l)
lineFeed(mySocket,2)
lineFeed(mySocket,4)
paperCut(mySocket)
mySocket.close()
if __name__=="__main__":
main()
This command generates one horizontal strip of the image at a time. The strip is either 8 or 24 dots tall, depending on the value of m.
nL and nH are the low and high bytes of an integer that specifies the width in dots of the horizontal strip of image. That width is computed as nL + nH * 256, so if you wanted the image to be 550 dots wide, then nH=2 and nL=38.
The argument d is the bitmap data; if the image strip is 8 dots tall, then each byte represents one column in the strip. If the strip is 24 dots tall, then three bytes represent one column.
So let's say you have arecibo in a WxH numpy array of ints, 1 or 0. You would:
data = np.zeros((W, H), dtype=np.ubyte)
## (fill in data here)
## Use m=33 since this is apparently the only mode with
## square pixels and also the highest resolution
## (unless it prints too slowly for your liking)
m = 33
nH = W // 256 ## note this is integer division, but SO's
## syntax hilighting thinks it looks like a comment.
nL = W % 256
## Divide the array into sections with shape Wx24:
for n in range(data.shape[1] // 24):
## Note that if the image height is not a multiple of 24,
## you'll have to pad it with zeros somehow.
strip = data[:, n*24:(n+1)*24]
## Convert each strip into a string of bytes:
strip = strip.reshape(W, 3, 8)
bytes = (strip * (2**np.arange(8)[np.newaxis, np.newaxis, :])).sum(axis=2) # magic
byteString = bytes.astype(np.ubyte).tostring()
## Send the command to POS