jules_verne

La totalité du projet sera documentée, mais pour l'instant, prise de note !

Transcodex graphique

→ dans le raspberryPi, pour lancer le script python automatiquement: login automatique en CLI Ajouter dans .bashrc les deux lignes suivantes: cd /home/pi/git/py-thermal-printer /usr/bin/python /home/pi/git/py-thermal-printer/codex.py

→ le script python:

#!/usr/bin/env python #coding=utf-8

import serial, struct, time

# to read key on unix import os import sys import termios import tty

# to print, … ha ha ha import Image, ImageDraw

import os.path

#===========================================================# # RASPBERRY PI (tested with Raspbian Jan 2012): # - Ensure that ttyAMA0 is not used for serial console access: # edit /boot/cmdline.txt (remove all name-value pairs containing # ttyAMA0) and comment out last line in /etc/inittab. # - Fix user permissions with “sudo usermod -a -G dialout pi” # - Reboot # - Ensure that the SERIALPORT setting is correct below # # BEAGLE BONE: # Mux settings (Ängström 2012.05, also work on ubuntu 12.04): # echo 1 > /sys/kernel/debug/omap_mux/spi0_sclk # echo 1 > /sys/kernel/debug/omap_mux/spi0_d0 #===========================================================#

print “Première ligne du script”

class ThermalPrinter(object):

  """ 
      
      Thermal printing library that controls the "micro panel thermal printer" sold in
      shops like Adafruit and Sparkfun (e.g. http://www.adafruit.com/products/597). 
      Mostly ported from Ladyada's Arduino library 
      (https://github.com/adafruit/Adafruit-Thermal-Printer-Library) to run on
      BeagleBone and Raspberry Pi.
      Currently handles printing image data and text, but the rest of the
      built-in functionality like underlining and barcodes are trivial
      to port to Python when needed.
      If on BeagleBone or similar device, remember to set the mux settings
      or change the UART you are using. See the beginning of this file for
      default setup.
      Thanks to Matt Richardson for the initial pointers on controlling the
      device via Python.
      @author: Lauri Kainulainen 
  """
  # default serial port for the Beagle Bone
  #SERIALPORT = '/dev/ttyO2'
  # this might work better on a Raspberry Pi
  SERIALPORT = '/dev/ttyAMA0'
  BAUDRATE = 19200
  TIMEOUT = 10
  # pixels with more color value (average for multiple channels) are counted as white
  # tweak this if your images appear too black or too white
  black_threshold = 64
  # pixels with less alpha than this are counted as white
  alpha_threshold = 127
  printer = None
  _ESC = chr(27)
  # These values (including printDensity and printBreaktime) are taken from 
  # lazyatom's Adafruit-Thermal-Library branch and seem to work nicely with bitmap 
  # images. Changes here can cause symptoms like images printing out as random text. 
  # Play freely, but remember the working values.
  # https://github.com/adafruit/Adafruit-Thermal-Printer-Library/blob/0cc508a9566240e5e5bac0fa28714722875cae69/Thermal.cpp
  
  # Set "max heating dots", "heating time", "heating interval"
  # n1 = 0-255 Max printing dots, Unit (8dots), Default: 7 (64 dots)
  # n2 = 3-255 Heating time, Unit (10us), Default: 80 (800us)
  # n3 = 0-255 Heating interval, Unit (10us), Default: 2 (20us)
  # The more max heating dots, the more peak current will cost
  # when printing, the faster printing speed. The max heating
  # dots is 8*(n1+1). The more heating time, the more density,
  # but the slower printing speed. If heating time is too short,
  # blank page may occur. The more heating interval, the more
  # clear, but the slower printing speed.
  
  def __init__(self, heatTime=80, heatInterval=2, heatingDots=7, serialport=SERIALPORT):
      print "Init Started"
self.printer = serial.Serial(serialport, self.BAUDRATE, timeout=self.TIMEOUT)
      self.printer.write(self._ESC) # ESC - command
      self.printer.write(chr(64)) # @   - initialize
      self.printer.write(self._ESC) # ESC - command
      self.printer.write(chr(55)) # 7   - print settings
      self.printer.write(chr(heatingDots))  # Heating dots (20=balance of darkness vs no jams) default = 20
      self.printer.write(chr(heatTime)) # heatTime Library default = 255 (max)
      self.printer.write(chr(heatInterval)) # Heat interval (500 uS = slower, but darker) default = 250
      # Description of print density from page 23 of the manual:
      # DC2 # n Set printing density
      # Decimal: 18 35 n
      # D4..D0 of n is used to set the printing density. Density is 50% + 5% * n(D4-D0) printing density.
      # D7..D5 of n is used to set the printing break time. Break time is n(D7-D5)*250us.
      printDensity = 15 # 120% (? can go higher, text is darker but fuzzy)
      printBreakTime = 15 # 500 uS
      self.printer.write(chr(18))
      self.printer.write(chr(35))
      self.printer.write(chr((printDensity << 4) | printBreakTime))
  def offline(self):
      # Take the printer offline. Print commands sent after this will be
      # ignored until 'online' is called.
      self.printer.write(self._ESC)
      self.printer.write(chr(61))
      self.printer.write(chr(0))
  def online(self):
      # Take the printer back online. Subsequent print commands will be obeyed.
      self.printer.write(self._ESC)
      self.printer.write(chr(61))
      self.printer.write(chr(1))
  def sleep(self):
      # Put the printer into a low-energy state immediately.
      self.sleep_after(1)  # Can't be 0, that means 'don't sleep'
  def sleep_after(self, seconds):
      # Put the printer into a low-energy state after the given number
      # of seconds.
      if seconds:
          time.sleep(seconds)
          self.printer.write(self._ESC)
          self.printer.write(chr(56))
          self.printer.write(chr(seconds))
          self.printer.write(chr(seconds >> 8))
  def wake(self):
      # Wake the printer from a low-energy state.
      self.printer.write(chr(255))
      time.sleep(0.05)
      self.printer.write(self._ESC)
      self.printer.write(chr(56))
      self.printer.write(chr(0))
      self.printer.write(chr(0))
  def has_paper(self):
      # Check the status of the paper using the printer's self reporting
      # ability. SerialTX _must_ be connected!
      self.printer.write(self._ESC)
      self.printer.write(chr(118))
      self.printer.write(chr(0))
      status = -1
      if self.printer.inWaiting() > 0:
          ret = self.printer.read()
          if ret:
              status = struct.unpack('b', ret)[0]
      return bool(status & 0b00000100)
  def reset(self):
      self.printer.write(self._ESC)
      self.printer.write(chr(64))
  def linefeed(self):
      self.printer.write(chr(10))
  def justify(self, align="L"):
      pos = 0
      if align == "L":
          pos = 0
      elif align == "C":
          pos = 1
      elif align == "R":
          pos = 2
      self.printer.write(self._ESC)
      self.printer.write(chr(97))
      self.printer.write(chr(pos))
  def bold_off(self):
      self.printer.write(self._ESC)
      self.printer.write(chr(69))
      self.printer.write(chr(0))
  def bold_on(self):
      self.printer.write(self._ESC)
      self.printer.write(chr(69))
      self.printer.write(chr(1))
  def font_b_off(self):
      self.printer.write(self._ESC)
      self.printer.write(chr(33))
      self.printer.write(chr(0))
  def font_b_on(self):
      self.printer.write(self._ESC)
      self.printer.write(chr(33))
      self.printer.write(chr(1))
  def underline_off(self):
      self.printer.write(self._ESC)
      self.printer.write(chr(45))
      self.printer.write(chr(0))
  def underline_on(self):
      self.printer.write(self._ESC)
      self.printer.write(chr(45))
      self.printer.write(chr(1))
  def inverse_off(self):
      self.printer.write(chr(29))
      self.printer.write(chr(66))
      self.printer.write(chr(0))
  def inverse_on(self):
      self.printer.write(chr(29))
      self.printer.write(chr(66))
      self.printer.write(chr(1))
  def upsidedown_off(self):
      self.printer.write(self._ESC)
      self.printer.write(chr(123))
      self.printer.write(chr(0))
  def upsidedown_on(self):
      self.printer.write(self._ESC)
      self.printer.write(chr(123))
      self.printer.write(chr(1))
      
  def barcode_chr(self, msg):
      self.printer.write(chr(29)) # Leave
      self.printer.write(chr(72)) # Leave
      self.printer.write(msg)     # Print barcode # 1:Abovebarcode 2:Below 3:Both 0:Not printed
      
  def barcode_height(self, msg):
      self.printer.write(chr(29))  # Leave
      self.printer.write(chr(104)) # Leave
      self.printer.write(msg)      # Value 1-255 Default 50
      
  def barcode_height(self):
      self.printer.write(chr(29))  # Leave
      self.printer.write(chr(119)) # Leave
      self.printer.write(chr(2))   # Value 2,3 Default 2
      
  def barcode(self, msg):
      """ Please read http://www.adafruit.com/datasheets/A2-user%20manual.pdf
          for information on how to use barcodes. """
      # CODE SYSTEM, NUMBER OF CHARACTERS        
      # 65=UPC-A    11,12    #71=CODEBAR    >1
      # 66=UPC-E    11,12    #72=CODE93    >1
      # 67=EAN13    12,13    #73=CODE128    >1
      # 68=EAN8    7,8    #74=CODE11    >1
      # 69=CODE39    >1    #75=MSI        >1
      # 70=I25        >1 EVEN NUMBER           
      self.printer.write(chr(29))  # LEAVE
      self.printer.write(chr(107)) # LEAVE
      self.printer.write(chr(65))  # USE ABOVE CHART
      self.printer.write(chr(12))  # USE CHART NUMBER OF CHAR 
      self.printer.write(msg)
      
  def print_text(self, msg, chars_per_line=None):
      """ Print some text defined by msg. If chars_per_line is defined, 
          inserts newlines after the given amount. Use normal '\n' line breaks for 
          empty lines. """ 
      if chars_per_line == None:
          self.printer.write(msg)
      else:
          l = list(msg)
          le = len(msg)
          for i in xrange(chars_per_line + 1, le, chars_per_line + 1):
              l.insert(i, '\n')
          self.printer.write("".join(l))
          print "".join(l)
  def print_markup(self, markup):
      """ Print text with markup for styling.
      Keyword arguments:
      markup -- text with a left column of markup as follows:
      first character denotes style (n=normal, b=bold, u=underline, i=inverse, f=font B)
      second character denotes justification (l=left, c=centre, r=right)
      third character must be a space, followed by the text of the line.
      """
      lines = markup.splitlines(True)
      for l in lines:
          style = l[0]
          justification = l[1].upper()
          text = l[3:]
          if style == 'b':
              self.bold_on()
          elif style == 'u':
             self.underline_on()
          elif style == 'i':
             self.inverse_on()
          elif style == 'f':
              self.font_b_on()
          self.justify(justification)
          self.print_text(text)
          if justification != 'L':
              self.justify()
          if style == 'b':
              self.bold_off()
          elif style == 'u':
             self.underline_off()
          elif style == 'i':
             self.inverse_off()
          elif style == 'f':
              self.font_b_off()
  def convert_pixel_array_to_binary(self, pixels, w, h):
      """ Convert the pixel array into a black and white plain list of 1's and 0's
          width is enforced to 384 and padded with white if needed. """
      black_and_white_pixels = [1] * 384 * h
      if w > 384:
          print "Bitmap width too large: %s. Needs to be under 384" % w
          return False
      elif w < 384:
          print "Bitmap under 384 (%s), padding the rest with white" % w
      print "Bitmap size", w
      if type(pixels[0]) == int: # single channel
          print " => single channel"
          for i, p in enumerate(pixels):
              if p < self.black_threshold:
                  black_and_white_pixels[i % w + i / w * 384] = 0
              else:
                  black_and_white_pixels[i % w + i / w * 384] = 1
      elif type(pixels[0]) in (list, tuple) and len(pixels[0]) == 3: # RGB
          print " => RGB channel"
          for i, p in enumerate(pixels):
              if sum(p[0:2]) / 3.0 < self.black_threshold:
                  black_and_white_pixels[i % w + i / w * 384] = 0
              else:
                  black_and_white_pixels[i % w + i / w * 384] = 1
      elif type(pixels[0]) in (list, tuple) and len(pixels[0]) == 4: # RGBA
          print " => RGBA channel"
          for i, p in enumerate(pixels):
              if sum(p[0:2]) / 3.0 < self.black_threshold and p[3] > self.alpha_threshold:
                  black_and_white_pixels[i % w + i / w * 384] = 0
              else:
                  black_and_white_pixels[i % w + i / w * 384] = 1
      else:
          print "Unsupported pixels array type. Please send plain list (single channel, RGB or RGBA)"
          print "Type pixels[0]", type(pixels[0]), "haz", pixels[0]
          return False
      return black_and_white_pixels
  def print_bitmap(self, pixels, w, h, output_png=False):
      """ Best to use images that have a pixel width of 384 as this corresponds
          to the printer row width. 
          
          pixels = a pixel array. RGBA, RGB, or one channel plain list of values (ranging from 0-255).
          w = width of image
          h = height of image
          if "output_png" is set, prints an "print_bitmap_output.png" in the same folder using the same
          thresholds as the actual printing commands. Useful for seeing if there are problems with the 
          original image (this requires PIL).
          Example code with PIL:
              import Image, ImageDraw
              i = Image.open("lammas_grayscale-bw.png")
              data = list(i.getdata())
              w, h = i.size
              p.print_bitmap(data, w, h)
      """
      counter = 0
      if output_png:
          import Image, ImageDraw
          test_img = Image.new('RGB', (384, h))
          draw = ImageDraw.Draw(test_img)
      self.linefeed()
      
      black_and_white_pixels = self.convert_pixel_array_to_binary(pixels, w, h)        
      print_bytes = []
      # read the bytes into an array
      for rowStart in xrange(0, h, 256):
          chunkHeight = 255 if (h - rowStart) > 255 else h - rowStart
          print_bytes += (18, 42, chunkHeight, 48)
          
          for i in xrange(0, 48 * chunkHeight, 1):
              # read one byte in
              byt = 0
              for xx in xrange(8):
                  pixel_value = black_and_white_pixels[counter]
                  counter += 1
                  # check if this is black
                  if pixel_value == 0:
                      byt += 1 << (7 - xx)
                      if output_png: draw.point((counter % 384, round(counter / 384)), fill=(0, 0, 0))
                  # it's white
                  else:
                      if output_png: draw.point((counter % 384, round(counter / 384)), fill=(255, 255, 255))
              
              print_bytes.append(byt)
      
      # output the array all at once to the printer
      # might be better to send while printing when dealing with 
      # very large arrays...
      for b in print_bytes:
          self.printer.write(chr(b))   
      
      if output_png:
          test_print = open('print-output.png', 'wb')
          test_img.save(test_print, 'PNG')
          print "output saved to %s" % test_print.name
          test_print.close()           

def getKey():

 fd = sys.stdin.fileno()
 old = termios.tcgetattr(fd)
 new = termios.tcgetattr(fd)
 new[3] = new[3] & ~termios.ICANON & ~termios.ECHO
 new[6][termios.VMIN] = 1
 new[6][termios.VTIME] = 0
 termios.tcsetattr(fd, termios.TCSANOW, new)
 key = None
 try:
    key = os.read(fd, 3)
 finally:
    termios.tcsetattr(fd, termios.TCSAFLUSH, old)
 return key

def PrintImage( ImageName) :

  i = Image.open( ImageName)
  data = list(i.getdata())
  w, h = i.size
  p.print_bitmap(data, w, h, False)
  p.linefeed()
  p.linefeed()
  p.linefeed()

if name == 'main':

  import sys, os

  	

  if len(sys.argv) == 2:
      serialport = sys.argv[1]
print "point d'arrêt n°1"
  else:
      serialport = ThermalPrinter.SERIALPORT
print "point d'arrêt n°2"
  if not os.path.exists(serialport):
      sys.exit("ERROR: Serial port not found at: %s" % serialport)
  print "Testing printer on port %s" % serialport
  
  p = ThermalPrinter(serialport=serialport)
  
  p.print_text("\nLes Voyages typo-graphiques\n")
  p.print_text("\nde Jules Verne\n")
  
  # runtime dependency on Python Imaging Library
  ImgArrays = {   'A':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_A.png'
                , 'B':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_B.png'
                , 'C':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_C.png'
                , 'D':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_D.png'
                , 'E':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_E.png'
                , 'F':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_F.png'
                , 'G':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_G.png'
                , 'H':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_H.png'
                , 'I':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_I.png'
                , 'J':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_J.png'
                , 'K':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_K.png'
                , 'L':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_L.png'
                , 'M':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_M.png'
                , 'N':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_N.png'
                , 'O':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_O.png'
                , 'P':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_P.png'
                , 'Q':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_Q.png'
                , 'R':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_R.png'
                , 'S':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_S.png'
                , 'T':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_T.png'
                , 'U':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_U.png'
                , 'V':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_V.png'
                , 'W':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_W.png'
                , 'X':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_X.png'
                , 'Y':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_Y.png'
                , 'Z':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_Z.png'
                , '0':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_0.png'
                , '1':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_1.png'
                , '2':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_2.png'
                , '3':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_3.png'
                , '4':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_4.png'
                , '5':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_5.png'
                , '6':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_6.png'
                , '7':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_7.png'
                , '8':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_8.png'
                , '9':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_9.png'
                , ' ':'/home/pi/git/py-thermal-printer/pics/VT_Codex_Thermique_00_Espace.png'
                }
  ch=''
  Cnt=0;
  while ch != '&':
      ch = getKey()
      if(('\n' == ch) or ('\r' == ch)):
          Cnt = 0
          # return char won't print
      elif(0 == Cnt):
          Cnt = 1
          # will print, next will not
      else:
          Cnt = 0
          ch = '\n'
          # won't print next will print
      if ch in ImgArrays :
          ImageName = ImgArrays[ch]
          if os.path.isfile(ImageName):
              # print('for %s printing %s' % (ch, ImageName))
               PrintImage( ImageName);
     #     else :
             # print('for %s do not find %s' % (ch, ImageName))
     # else :
         # print(' no pics defined for %s ... sniff'% ch)
     

→ dans le clavier en kapla, un arduino Leonardo:

#include <Keypad.h> #include <Adafruit_NeoPixel.h>

Which pin on the Arduino is connected to the NeoPixels? On a Trinket or Gemma we suggest changing this to 1 #define PIN 13

How many NeoPixels are attached to the Arduino? #define NUMPIXELS 14 When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals. Note that for older NeoPixel strips you might need to change the third parameter–see the strandtest example for more information on possible values. Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int delayval = 13500; delay for half a second const int spacePin = 12; the number of the pushbutton pin int buttonPressed = 0; variable for reading the pushbutton status int printing = 0; const byte ROWS = 6; four rows const byte COLS = 6; three columns char keys[ROWS][COLS] = { {'0', '1', '2', '3', '4', '5'}, {'A', 'B', 'C', 'D', 'E', 'F'}, {'N', 'O', 'P', 'Q', 'R', 'S'}, {'T', 'U', 'V', 'W', 'X', 'Y'}, {'G', 'H', 'I', 'J', 'K', 'L'}, {'6', '7', '8', '9', 'M', 'Z'} }; byte rowPins[ROWS] = {6, 7, 8, 9, 10, 11}; connect to the row pinouts of the keypad byte colPins[COLS] = {0, 1, 2, 3, 4, 5}; connect to the column pinouts of the keypad Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); void setup() { pixels.begin(); This initializes the NeoPixel library.

Keyboard.begin();
pinMode(spacePin, INPUT_PULLUP);
//Serial.begin(9600);

}

void loop() {

if (printing == 0)
{
  lightsGreen();
  int sensorVal = digitalRead(12);
  if (sensorVal == LOW && buttonPressed == 0) {
    buttonPressed = 1;
    //Serial.println("SPACE");
    Keyboard.write(0x20);
    Keyboard.releaseAll();  
    printing = 1;
    lightsRed();
    delay(delayval); // Delay for a period of time (in milliseconds).
    Keyboard.write(0x20);
    Keyboard.releaseAll(); 
    delay(200);
    Keyboard.write(0xB0);
    Keyboard.releaseAll(); 
    delay(200);
    printing = 0;
  } else if (sensorVal == HIGH && buttonPressed == 1) {
    buttonPressed = 0;
  }
  
  char key = keypad.getKey();
  if (key) {
    //Serial.println(key);
    Keyboard.write(key);
    Keyboard.releaseAll();  
    printing = 1;
    lightsRed();
    delay(delayval); // Delay for a period of time (in milliseconds).
    Keyboard.write(key);
    Keyboard.releaseAll(); 
    delay(200);
    Keyboard.write(0xB0);
    Keyboard.releaseAll(); 
    delay(200);
    printing = 0;
  }
}

}

void lightsGreen() {

for (int i = 0; i < NUMPIXELS; i++) {
  // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
  pixels.setPixelColor(i, pixels.Color(0, 255, 0)); // Moderately bright green color.
  pixels.show(); // This sends the updated pixel color to the hardware.
}

}

void lightsRed() {

for (int i = 0; i < NUMPIXELS; i++) {
  // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
  pixels.setPixelColor(i, pixels.Color(255, 0, 0)); // Moderately bright green color.
  pixels.show(); // This sends the updated pixel color to the hardware.
}

}

  • jules_verne.txt
  • Dernière modification: 2016/03/04 08:08
  • (modification externe)