What is the difference between Serial.write and Serial.print? And when are they used?
Serial.write is more down to earth , it is simple and fast, it is made to talk binary, one byte at a time.
example:

Serial.write(0x45);   // will write 0100 0101 to the cable


Serial.print in the other hand is more versatile , it will do the conversion for you from ASCII to binary it also can convert to BIN/ HEX/OCT/DEC but you need to specify a second argument like so 

Serial.print(76, BIN) gives "0100 1100"
Serial.print(76, OCT) gives "114"
Serial.print("L", DEC) gives "76"
Serial.print(76, HEX) gives "4C" 


more examples with visual serial output :

Code:

  Serial.write(0x48);   // H
  Serial.write(0x45);   // E
  Serial.write(0x4C);   // L
  Serial.write(0x4C);   // L
  Serial.write(0x4F);   // O


SERIAL OUTPUT : 


Code:

  Serial.print("HELLO");


SERIAL OUTPUT :


Serial.println() in the other hand will add end of line 2 bytes 0x0D and 0x0A as you can see in the frame 

Code:

  Serial.println("HELLO");


SERIAL OUTPUT :