├── .gitignore ├── 3dprinting ├── LickometerHolder │ ├── Readme.md │ ├── operant_chamber_spout_holder_plate.scad │ ├── operant_chamber_spout_holder_plate.stl │ ├── rat.spout.holder.plate.stl │ ├── rat.water.holder.plate.FCStd │ ├── rat.water.spout.e-phyis.faceplate.fcstd │ ├── rat.water.spout.holder.tilted.fcstd │ ├── ratSpoutHolderPlate.scad │ ├── water.spout.holder.ephyis.face.plate.stl │ └── waterbottleholder.tiltedbottom.stl ├── Readme.md ├── ball │ ├── ball.scad │ ├── ball_hi_res.stl │ └── ball_lo_res.stl ├── brainMatrix │ ├── Readme.md │ ├── brainMatrix.scad │ ├── brainMatrix_assembled.stl │ ├── brainMatrix_base.stl │ ├── brainMatrix_cutter.stl │ └── brainMatrix_slider.stl ├── mouseBoxDivider │ ├── MoueBoxInsertPart1.fcstd │ ├── MouseBoxInsertPart2.fcstd │ ├── Readme.md │ ├── mouseBoxDividerPart1.stl │ └── mouseBoxDividerPart2.stl ├── mouseNosePokeInRatBox │ ├── Readme.md │ ├── mouseNosePokeForRat.stl │ └── nosepokeAdapt.fcstd ├── mouseRestraint │ └── mouseRestraint.scad ├── mouse_eartag │ ├── mouse_eartag.scad │ └── mouse_eartag.stl ├── operantChamberTopCover │ ├── Readme.md │ ├── rat.operant.chamber.center.cover.fcstd │ └── rat.operant.chamber.center.cover.stl ├── poopScoop │ ├── RatPoopScoop.fcstd │ ├── Readme.md │ └── ratPoopScoop.stl ├── raspberrypi_camer_case │ ├── rpi_camera_mount.scad │ └── rpi_camera_mount.stl ├── ratButton │ ├── Readme.md │ ├── ratButton.scad │ ├── ratButton.scad_original │ └── ratButton.stl ├── rat_eartag │ ├── rat_eartag.scad │ └── rat_eartag.stl └── steps4ElevatedPlusMaze │ ├── plusmaze_openfield_corner_fasterner.scad │ └── plusmazeboots.scad ├── README.md ├── RFID ├── Adafruit_CharLCD.py ├── RDM630-Spec.pdf ├── Rdm6300UART.py ├── Rdm6300_USB.py ├── Readme.md ├── Untitled.scad ├── connections.txt ├── install.sh ├── rfidReaderCase.scad ├── rfidReaderCase.stl ├── rfidReaderFront.stl ├── rfidReaderTop.stl ├── rfidReaderTopCover.stl ├── rfidscanner.py ├── rfidscanner.service └── settingUpUART.readme ├── RFID_eInk_Reader ├── Readme.md ├── a_rfid.py ├── rfid_reader_eink.py ├── rfid_reader_eink.scad ├── rfid_reader_eink.stl ├── rfid_reader_eink_box.stl └── rfid_reader_eink_cover.stl ├── RPI.PinLables.pdf ├── envSensors ├── 3D_design_frame │ ├── envSensorBoard.scad │ └── envSensorBoard.stl ├── Adafruit_I2C.py ├── HTU21DF.py ├── Readme.md ├── SampleData.tab ├── TSL2561.py ├── bmp.py ├── checklux.py ├── env_logger.cron.py ├── images │ ├── envSensor1.jpg │ ├── envSensor2.jpg │ ├── envSensor3.jpg │ ├── envSensor4.jpg │ └── envSensor5.jpg └── setup_scripts │ ├── setup.sh │ ├── setup_auto_log_copy.sh │ └── setup_ds1307.sh ├── extinction ├── ExtinctionBoxWiring.ods ├── Readme.md ├── cuelights.py ├── extinction.py ├── extinctionCase.scad ├── extinctionCase.stl ├── extinctionCaseCover.stl ├── extinctionCueLightBox.stl ├── extinctionCueLightPlate.stl └── extinctionLEDBox.scad ├── infrared ├── MiceTunnels │ ├── DuralLayerPCBForIRDetections.jpg │ ├── OneWayDoorClosed.jpg │ ├── OneWayDoorOpen.jpg │ └── SixTunnelsForMiceWithOneWayDoors.jpg ├── board │ ├── ir.GBL │ ├── ir.GBO │ ├── ir.GBS │ ├── ir.GTL │ ├── ir.GTS │ ├── ir.TXT │ ├── ir.b## │ ├── ir.b#1 │ ├── ir.b#4 │ ├── ir.b#5 │ ├── ir.b#6 │ ├── ir.brd │ ├── ir.dri │ ├── ir.dru │ ├── ir.gpi │ ├── ir.pdf │ └── ir.sch ├── gpio.ir.py └── parts_list.txt ├── motion ├── Readme.md ├── motion.py ├── motionSensorCaseOP.stl ├── motionSensorCaseOPCover.stl └── motionSensorCaseOperantChamber.scad ├── openscad ├── project.scad └── pump_design │ ├── design.scad │ ├── endPiece.scad │ └── middlePieceModified.scad ├── operantLeverPressing ├── 1video.h264 ├── 2video.h264 ├── Readme.md ├── bmp183.py ├── bmp183.pyc ├── data.txt ├── htu21d.py ├── htu21d.pyc ├── leverRecord.py ├── measure.py ├── operant.py ├── scratch │ ├── sensor-test.py │ ├── start-scratch-program.py │ ├── test.sb │ └── test1.py ├── sensor.py ├── temperature and humidity │ ├── HTU21DF.py │ ├── HTU21DF.pyc │ └── HTU21DF_Logger.py ├── temperature.csv ├── templogs │ └── temperature.csv └── weather_to_statsd.py ├── operantLicking ├── Assembly.md ├── PartsList.md ├── Readme.md ├── images │ ├── LCD1.jpg │ ├── LCD2.jpg │ ├── LCD_connections.jpg │ ├── RFID_antenna.jpg │ ├── RFID_antenna2.jpg │ ├── RFID_antenna3.jpg │ ├── RFID_board1.jpg │ ├── RFID_board2.jpg │ ├── Rpi_pins.jpg │ ├── SwitchBoardBack2.jpg │ ├── assembled.jpg │ ├── cuelight.jpg │ ├── cuelight2.jpg │ ├── frame0.jpg │ ├── inRatCage.jpg │ ├── microUSB.jpg │ ├── motion_sensor.jpg │ ├── rfid2.jpg │ ├── spout.jpg │ ├── stepMotorBoardBack.jpg │ ├── stepMotorShaft.jpg │ ├── stepMotorWires.jpg │ ├── switchBoardBack.jpg │ ├── switchBoardFront.jpg │ ├── syringCarrier.jpg │ ├── syringEnd.jpg │ ├── syringPumbAssembled.jpg │ ├── syrngeLoaded.jpg │ ├── threadedRod.jpg │ ├── voltageConverter.jpg │ └── wires.jpg ├── openscad │ ├── alcoholSelfAdminFrame.scad │ ├── alcoholSelfAdminFrame_Bottom.stl │ ├── alcoholSelfAdminFrame_Cover.stl │ ├── alcoholSelfAdminFrame_Top.stl │ ├── alcoholSelfAdmin_RFIDDoor.stl │ ├── alcoholSelfAdmin_RFIDFrame.stl │ ├── alcoholSelfAdmin_SpoutHolder.stl │ ├── alcoholSelfAdmin_cueLightFastner.stl │ ├── alcoholSelfAdmin_stepMotorFastner.stl │ ├── bearings.scad │ ├── fasteners.scad │ ├── pump_assembly.scad │ ├── stepmotor_fastner.scad │ └── steppers.scad ├── python │ ├── blinkenlights.py │ ├── datalogger.py │ ├── main.py │ ├── motion.py │ ├── motor2.py │ ├── pumpcontrol.py │ ├── pumpinterface.py │ ├── pumpmove.py │ └── touchsensor.py ├── scripts │ └── rpi3.sh └── wiring_tables.ods ├── operantSensationSeeking ├── README.md ├── blink.py ├── errorled.py ├── freecad │ ├── Readme.md │ ├── rfid.annt.lid.stl │ ├── rfid.annte.stl │ ├── roof.stl │ ├── touchOSSwithBattery.stl │ └── touchoss.Battery.fcstd ├── motion.py ├── ossByTouch.py ├── ossHabituation.py └── touchled.py ├── ratremor ├── Readme.md ├── ratremor_prototype.jpg └── tremor.py ├── rtc ├── hwclock.sh └── remove_fake_hwclock.sh ├── socialDrinking ├── openscad │ ├── rfid_water_spout_cboard_cover.stl │ ├── rfid_waterspout.scad │ ├── rfid_waterspout_complete.stl │ ├── rfid_waterspout_entire_unit.stl │ ├── rfid_waterspout_front_panel.stl │ ├── rfid_waterspout_holder.stl │ └── rfid_waterspout_ring_cover.stl ├── python │ ├── Pies │ │ └── Oxycodone │ │ │ └── Oxy_Box1_S1_dkfasl_dfkas;jf.csv │ ├── PigpioStepperMotor.py │ ├── PumpTest.py │ ├── __pycache__ │ │ ├── PigpioStepperMotor.cpython-35.pyc │ │ ├── datalogger.cpython-35.pyc │ │ ├── ids.cpython-35.pyc │ │ ├── mover_subproc.cpython-35.pyc │ │ └── pump_move.cpython-35.pyc │ ├── blinkenlights.py │ ├── datalogger.py │ ├── deviceid │ ├── err.txt │ ├── ids.py │ ├── log.err │ ├── main.py │ ├── mover_subproc.py │ ├── operant.py │ ├── pump_move.py │ ├── pumpmove.py │ ├── ratids │ ├── sessionid │ ├── timers.py │ ├── touchsensor.py │ └── turnoff_light.py └── utility_script │ ├── check_empty_program.sh │ ├── printEmptySyringeInfo.sh │ ├── test.csv │ └── update_and_reboot.sh ├── tailTimer ├── config.py ├── readme.md ├── runtailtimer.sh ├── tailTimer.jpg ├── tailTimerCase.scad └── tailwithdrawal.py ├── touchscreen ├── circle.png ├── star.png └── touchscreen.py └── wifi-network ├── cronsync.sh ├── deviceinfo.sh ├── interfaces ├── killhtpd.sh ├── rsync.sh ├── wlan0down.sh └── wpa_supplicant.conf /.gitignore: -------------------------------------------------------------------------------- 1 | .pyc 2 | .stl 3 | __pycache__/ -------------------------------------------------------------------------------- /3dprinting/LickometerHolder/Readme.md: -------------------------------------------------------------------------------- 1 | # Water spout holder for operant chambers 2 | 3 | The tilted bottom one prevents extra liquid causing short circuits. The tall one allows rats with head stages to access the spout. These fits in the standard operant chambers for rats. 4 | 5 | -------------------------------------------------------------------------------- /3dprinting/LickometerHolder/operant_chamber_spout_holder_plate.scad: -------------------------------------------------------------------------------- 1 | difference(){ 2 | cube([77,88,2]); 3 | translate([13.5,10,-1])cube([50,50,4]); 4 | translate([38.5,72, 0]) screw(); 5 | translate([8.5, 40,0]) screw(); 6 | translate([68.5,40,0]) screw(); 7 | } 8 | 9 | 10 | module screw(){ 11 | cylinder(r1=3.8, r2=2, h=2); 12 | } 13 | -------------------------------------------------------------------------------- /3dprinting/LickometerHolder/rat.spout.holder.plate.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/3dprinting/LickometerHolder/rat.spout.holder.plate.stl -------------------------------------------------------------------------------- /3dprinting/LickometerHolder/rat.water.holder.plate.FCStd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/3dprinting/LickometerHolder/rat.water.holder.plate.FCStd -------------------------------------------------------------------------------- /3dprinting/LickometerHolder/rat.water.spout.e-phyis.faceplate.fcstd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/3dprinting/LickometerHolder/rat.water.spout.e-phyis.faceplate.fcstd -------------------------------------------------------------------------------- /3dprinting/LickometerHolder/rat.water.spout.holder.tilted.fcstd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/3dprinting/LickometerHolder/rat.water.spout.holder.tilted.fcstd -------------------------------------------------------------------------------- /3dprinting/LickometerHolder/ratSpoutHolderPlate.scad: -------------------------------------------------------------------------------- 1 | $fn=100; 2 | difference(){ 3 | 4 | cube([77,82,1.8]); // plate per se 5 | translate([13,21,-1]) cube([50,50,3]); // open in the middle 6 | translate([77/2,10,-1]) cylinder(r1=1.8, r2=3, h=3); // screw 7 | translate([8.5,42.5,-1]) cylinder(r1=1.8, r2=3, h=3); // screw 8 | translate([68.5,42.5,-1]) cylinder(r1=1.8, r2=3,h=3); // screw 9 | 10 | } 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /3dprinting/LickometerHolder/water.spout.holder.ephyis.face.plate.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/3dprinting/LickometerHolder/water.spout.holder.ephyis.face.plate.stl -------------------------------------------------------------------------------- /3dprinting/LickometerHolder/waterbottleholder.tiltedbottom.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/3dprinting/LickometerHolder/waterbottleholder.tiltedbottom.stl -------------------------------------------------------------------------------- /3dprinting/Readme.md: -------------------------------------------------------------------------------- 1 | Design files for 3D printing 2 | ============================== 3 | 4 | The frames or cases used for the various devices are located in the devices folder. Here are some misc. objects that we use in the lab. Older files were designed using using FreeCAD. Newer files were designed uing Openscad. You can click on the .stl file and view a 3D rendering of the design using Github's built-in viewer. 5 | 6 | 7 | -------------------------------------------------------------------------------- /3dprinting/ball/ball.scad: -------------------------------------------------------------------------------- 1 | $fn=40; 2 | $fn=13; 3 | module bar(){ 4 | difference(){ 5 | cylinder(r1=14, r2=8, h=106, center=true); 6 | cylinder(r1=12, r2=6, h=104, center=true); 7 | } 8 | } 9 | 10 | difference (){ 11 | radius=50; 12 | union(){ 13 | sphere(r=radius); 14 | bar(); 15 | rotate([90,0,0]) bar(); 16 | rotate([0,90,0]) bar(); 17 | } 18 | sphere(r=radius-2); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /3dprinting/brainMatrix/Readme.md: -------------------------------------------------------------------------------- 1 | # Brain slicer 2 | 3 | ## Assembly 4 | See brainMatrix_assembled.stl. The other three stl files are for printing. 5 | 6 | ## Procedure 7 | A fresh rat brain is placed in the cutter. Single edge blades are then lowered into the guide slots of the cutter to cut the brain at 1 mm intervals. The slider is then moved out, allowing the cutter to be lowered into the base. The side bars of the base catch the blades and allow the brain sections to be removed one at a time. 8 | 9 | 10 | -------------------------------------------------------------------------------- /3dprinting/brainMatrix/brainMatrix.scad: -------------------------------------------------------------------------------- 1 | $fn=100; 2 | module slider(){ 3 | difference(){ 4 | translate([0,-8,9])cube([28,28,14], center=true); 5 | translate([0,-6,9]) cube ([14,28,15], center=true); 6 | } 7 | } 8 | 9 | module cutter(){ 10 | difference(){ 11 | cube ([26,26,14], center=true); // outside 12 | translate([0,4,0]) cube ([14,26,15], center=true); // inside 13 | for (i = [3:6]) { 14 | translate([0,i,1]) cube ([30,0.4,14], center=true); // knife cuts 15 | } 16 | } 17 | } 18 | 19 | module base(){ 20 | cube ([38,40,4], center=true); 21 | translate([0,6,9]) cube ([13,28,17], center=true); 22 | translate([-19,0,2])side(); 23 | translate([15,0,2])side(); 24 | } 25 | 26 | module side(){ 27 | // translate([16,13,13]) cube([4,2,h], center=true); 28 | // translate([-16,13,13]) cube([4,2,h], center=true); 29 | translate([0,-2,0]) cube([4,9,h]); 30 | h=14; 31 | translate([0,5,h]) cube([4,2,h]); 32 | translate([0,-2,h]) cube([4,2,h]); 33 | } 34 | 35 | 36 | color("yellow") translate([0,5,0]) slider(); // 37 | translate([0,-2,23]) cutter(); 38 | 39 | color("grey") base(); 40 | 41 | -------------------------------------------------------------------------------- /3dprinting/brainMatrix/brainMatrix_slider.stl: -------------------------------------------------------------------------------- 1 | solid OpenSCAD_Model 2 | facet normal -1 0 0 3 | outer loop 4 | vertex -14 -17 2 5 | vertex -14 11 16 6 | vertex -14 11 2 7 | endloop 8 | endfacet 9 | facet normal -1 -0 0 10 | outer loop 11 | vertex -14 11 16 12 | vertex -14 -17 2 13 | vertex -14 -17 16 14 | endloop 15 | endfacet 16 | facet normal 0 0 1 17 | outer loop 18 | vertex -7 11 16 19 | vertex -14 11 16 20 | vertex -7 -15 16 21 | endloop 22 | endfacet 23 | facet normal 0 0 1 24 | outer loop 25 | vertex 7 -15 16 26 | vertex 14 11 16 27 | vertex 7 11 16 28 | endloop 29 | endfacet 30 | facet normal 0 0 1 31 | outer loop 32 | vertex 14 11 16 33 | vertex 7 -15 16 34 | vertex 14 -17 16 35 | endloop 36 | endfacet 37 | facet normal -0 0 1 38 | outer loop 39 | vertex -7 -15 16 40 | vertex 14 -17 16 41 | vertex 7 -15 16 42 | endloop 43 | endfacet 44 | facet normal 0 0 1 45 | outer loop 46 | vertex -7 -15 16 47 | vertex -14 -17 16 48 | vertex 14 -17 16 49 | endloop 50 | endfacet 51 | facet normal 0 0 1 52 | outer loop 53 | vertex -14 -17 16 54 | vertex -7 -15 16 55 | vertex -14 11 16 56 | endloop 57 | endfacet 58 | facet normal 1 -0 0 59 | outer loop 60 | vertex 14 -17 16 61 | vertex 14 11 2 62 | vertex 14 11 16 63 | endloop 64 | endfacet 65 | facet normal 1 0 0 66 | outer loop 67 | vertex 14 11 2 68 | vertex 14 -17 16 69 | vertex 14 -17 2 70 | endloop 71 | endfacet 72 | facet normal 0 0 -1 73 | outer loop 74 | vertex 14 -17 2 75 | vertex 7 -15 2 76 | vertex 14 11 2 77 | endloop 78 | endfacet 79 | facet normal 0 0 -1 80 | outer loop 81 | vertex 14 -17 2 82 | vertex -7 -15 2 83 | vertex 7 -15 2 84 | endloop 85 | endfacet 86 | facet normal 0 0 -1 87 | outer loop 88 | vertex -14 -17 2 89 | vertex -7 -15 2 90 | vertex 14 -17 2 91 | endloop 92 | endfacet 93 | facet normal 0 0 -1 94 | outer loop 95 | vertex -14 11 2 96 | vertex -7 -15 2 97 | vertex -14 -17 2 98 | endloop 99 | endfacet 100 | facet normal 0 0 -1 101 | outer loop 102 | vertex -7 -15 2 103 | vertex -14 11 2 104 | vertex -7 11 2 105 | endloop 106 | endfacet 107 | facet normal -0 0 -1 108 | outer loop 109 | vertex 14 11 2 110 | vertex 7 -15 2 111 | vertex 7 11 2 112 | endloop 113 | endfacet 114 | facet normal 0 -1 0 115 | outer loop 116 | vertex -14 -17 2 117 | vertex 14 -17 16 118 | vertex -14 -17 16 119 | endloop 120 | endfacet 121 | facet normal 0 -1 -0 122 | outer loop 123 | vertex 14 -17 16 124 | vertex -14 -17 2 125 | vertex 14 -17 2 126 | endloop 127 | endfacet 128 | facet normal 0 1 -0 129 | outer loop 130 | vertex 14 11 2 131 | vertex 7 11 16 132 | vertex 14 11 16 133 | endloop 134 | endfacet 135 | facet normal 0 1 0 136 | outer loop 137 | vertex 7 11 16 138 | vertex 14 11 2 139 | vertex 7 11 2 140 | endloop 141 | endfacet 142 | facet normal 0 1 -0 143 | outer loop 144 | vertex -7 11 2 145 | vertex -14 11 16 146 | vertex -7 11 16 147 | endloop 148 | endfacet 149 | facet normal 0 1 0 150 | outer loop 151 | vertex -14 11 16 152 | vertex -7 11 2 153 | vertex -14 11 2 154 | endloop 155 | endfacet 156 | facet normal 1 -0 0 157 | outer loop 158 | vertex -7 -15 16 159 | vertex -7 11 2 160 | vertex -7 11 16 161 | endloop 162 | endfacet 163 | facet normal 1 0 0 164 | outer loop 165 | vertex -7 11 2 166 | vertex -7 -15 16 167 | vertex -7 -15 2 168 | endloop 169 | endfacet 170 | facet normal -1 0 0 171 | outer loop 172 | vertex 7 -15 2 173 | vertex 7 11 16 174 | vertex 7 11 2 175 | endloop 176 | endfacet 177 | facet normal -1 -0 0 178 | outer loop 179 | vertex 7 11 16 180 | vertex 7 -15 2 181 | vertex 7 -15 16 182 | endloop 183 | endfacet 184 | facet normal 0 1 -0 185 | outer loop 186 | vertex 7 -15 2 187 | vertex -7 -15 16 188 | vertex 7 -15 16 189 | endloop 190 | endfacet 191 | facet normal 0 1 0 192 | outer loop 193 | vertex -7 -15 16 194 | vertex 7 -15 2 195 | vertex -7 -15 2 196 | endloop 197 | endfacet 198 | endsolid OpenSCAD_Model 199 | -------------------------------------------------------------------------------- /3dprinting/mouseBoxDivider/MoueBoxInsertPart1.fcstd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/3dprinting/mouseBoxDivider/MoueBoxInsertPart1.fcstd -------------------------------------------------------------------------------- /3dprinting/mouseBoxDivider/MouseBoxInsertPart2.fcstd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/3dprinting/mouseBoxDivider/MouseBoxInsertPart2.fcstd -------------------------------------------------------------------------------- /3dprinting/mouseBoxDivider/Readme.md: -------------------------------------------------------------------------------- 1 | These two part fit together to divide a mouse box into three parts. This allows three mice to be put in the same box after surgery. So they can still have social interaction and not bite each other's wound. 2 | -------------------------------------------------------------------------------- /3dprinting/mouseBoxDivider/mouseBoxDividerPart1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/3dprinting/mouseBoxDivider/mouseBoxDividerPart1.stl -------------------------------------------------------------------------------- /3dprinting/mouseBoxDivider/mouseBoxDividerPart2.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/3dprinting/mouseBoxDivider/mouseBoxDividerPart2.stl -------------------------------------------------------------------------------- /3dprinting/mouseNosePokeInRatBox/Readme.md: -------------------------------------------------------------------------------- 1 | This adapter allows us to install a nose poke sensor designed for mouse operant chambers in rat operant chambers. 2 | -------------------------------------------------------------------------------- /3dprinting/mouseNosePokeInRatBox/mouseNosePokeForRat.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/3dprinting/mouseNosePokeInRatBox/mouseNosePokeForRat.stl -------------------------------------------------------------------------------- /3dprinting/mouseNosePokeInRatBox/nosepokeAdapt.fcstd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/3dprinting/mouseNosePokeInRatBox/nosepokeAdapt.fcstd -------------------------------------------------------------------------------- /3dprinting/mouseRestraint/mouseRestraint.scad: -------------------------------------------------------------------------------- 1 | $fn=100; 2 | !rotate([180,0,180]) translate([0,0,-55]) color("blue") cover(); 3 | innerR=15; 4 | difference(){ 5 | cylinder(r=18, h=110, center=true); 6 | cylinder(r=innerR, h=111, center=true); 7 | ventHole(); 8 | translate([0,0,25]) ventHole(); 9 | translate([0,0,-25]) ventHole(); 10 | translate([-15,0,-20])cube([10,3,80], center=true ); // later cut 11 | translate([0,-15,-20])cube([8,10,80], center=true ); // top cut head end 12 | translate([0,-13,63])cube([4,10,30], center=true ); // top cut tail end 13 | translate([-4,-14,50]) rotate([90,225,0]) slit(); // tail end screw slit 14 | slit2(); 15 | translate([0,0,12]) slit2(); 16 | translate([0,0,-12]) slit2(); 17 | translate([0,0,-24]) slit2(); 18 | translate([0,0,-36]) slit2(); 19 | translate([0,0,-48]) slit2(); 20 | 21 | } 22 | 23 | module ventHole() { 24 | rotate([0,90,0])translate([0,0,20]) cylinder (r=3, h=40, center=true); 25 | } 26 | 27 | module slit2() { 28 | translate([-13,3,0])rotate([0,90,0]) slit(); 29 | } 30 | 31 | module slit(){ 32 | cylinder(r=1.9, h=10, center=true); 33 | rotate([0,0,135]) translate([0,2,0]) cube([4,4,10], center=true); 34 | } 35 | 36 | module cover(){ 37 | h2=8; 38 | difference(){ 39 | union(){ 40 | translate([0,0,h2/2]) cylinder(r=innerR-.7, h=h2, center=true); 41 | cylinder(r=17, h=2, center=true); 42 | } 43 | translate([0,-1,0]) rotate([0,0,90]) cylinder(r=3.2, h=25, center=true); 44 | translate([0,14,0]) cube([6.4,30,17], center=true ); // verticl cut 45 | rotate([90,0,0]) translate([0,5,0]) cylinder(r=2.1,h=20); //screw small =1.8, large=2.1 46 | //translate([0,-9,0]) cube ([6,3,9], center=true) ; //hex nut 47 | } 48 | } 49 | 50 | 51 | //translate([0,0,-50]) color("red") nosecone(); 52 | module nosecone() { 53 | difference (){ 54 | cylinder(r=innerR-0.5, h=38); 55 | translate([0,0,-.1])cylinder(r2=innerR-1, r1=5, h=39); 56 | rotate([90,0,-90]) translate([0,3,4]) cylinder(r=2.1,h=18); //screw 57 | translate([0,-7,26])cube([8,16,25], center=true ); // top cut head end 58 | } 59 | } 60 | 61 | 62 | //!cover2(); // models the original cover 63 | module cover2(){ 64 | difference(){ 65 | union(){ 66 | difference(){ 67 | cylinder(r=18.5, h=2, center=true); 68 | translate([0,-15,0])cube([40,20,2], center=true); 69 | } 70 | h2=7; translate([0,0,h2/2-1]) cylinder(r=15, h=h2, center=true); 71 | 72 | } 73 | translate([0,10,0]) rotate([0,0,90]) cylinder(r=4, h=25, center=true); 74 | translate([0,14,0]) cube([8,10,17], center=true ); // verticl cut 75 | rotate([90,0,0]) translate([0,3,6]) cylinder(r=1.4,h=10); //screw 76 | rotate([0,90,0]) translate([-6,-6,0]) cylinder(r=4,h=50, center=true); // horizontal groove 77 | translate([0,4,4])cube([40,25,4], center=true); 78 | } 79 | } 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /3dprinting/mouse_eartag/mouse_eartag.scad: -------------------------------------------------------------------------------- 1 | $fn=60; 2 | 3 | difference(){ 4 | cylinder(r=3.9, h=0.8); // top above the base 5 | cylinder(r=0.62, h=30, center=true); // was .42 center hole 6 | } 7 | 8 | #difference(){ 9 | cylinder(r=3.9, h=3); 10 | cylinder(r=3.1, h=3); 11 | translate([-4,1,.5])cube([8,8,4]); 12 | } 13 | -------------------------------------------------------------------------------- /3dprinting/operantChamberTopCover/Readme.md: -------------------------------------------------------------------------------- 1 | A cover for the top center hole of rat operant chamber to allow a spring to go through and prevent the rat from escaping. 2 | 3 | -------------------------------------------------------------------------------- /3dprinting/operantChamberTopCover/rat.operant.chamber.center.cover.fcstd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/3dprinting/operantChamberTopCover/rat.operant.chamber.center.cover.fcstd -------------------------------------------------------------------------------- /3dprinting/operantChamberTopCover/rat.operant.chamber.center.cover.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/3dprinting/operantChamberTopCover/rat.operant.chamber.center.cover.stl -------------------------------------------------------------------------------- /3dprinting/poopScoop/RatPoopScoop.fcstd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/3dprinting/poopScoop/RatPoopScoop.fcstd -------------------------------------------------------------------------------- /3dprinting/poopScoop/Readme.md: -------------------------------------------------------------------------------- 1 | Well, the name says it all. 2 | -------------------------------------------------------------------------------- /3dprinting/poopScoop/ratPoopScoop.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/3dprinting/poopScoop/ratPoopScoop.stl -------------------------------------------------------------------------------- /3dprinting/raspberrypi_camer_case/rpi_camera_mount.scad: -------------------------------------------------------------------------------- 1 | // original design by devzero, published Oct 19, 2013 2 | // https://www.thingiverse.com/thing:168581 3 | // modified by Hao Chen Oct 11 2017 4 | 5 | board_width=25.5; 6 | board_height=23; 7 | board_thick=4.75; 8 | cable_width=18; 9 | cable_thick=1; 10 | side_cover=7.5; 11 | camera_hole_width=10; 12 | camera_hole_height=5.5; 13 | screw_hole_r=2.65; 14 | padding=2.5; 15 | d=0.001; 16 | mount_offset=2*padding+board_width; 17 | mount_thickness=8; 18 | 19 | 20 | //camera holder 21 | difference(){ 22 | cube([board_thick+2*padding, board_width+2*padding, board_height+2*padding]); 23 | //main compartment 24 | translate([padding, padding, padding]) cube([board_thick, board_width, board_height+padding+d]); 25 | //front camera slot 26 | translate([board_thick+padding-d, padding+side_cover, padding+camera_hole_height]) cube([padding+2*d, camera_hole_width, board_height+padding-camera_hole_height+d]); 27 | //hole for cable in the bottom 28 | translate([padding+2,padding+(board_width-cable_width)/2,0]) cube([cable_thick, cable_width+2*d, padding+2*d]); 29 | } 30 | 31 | //handle 32 | 33 | translate([7.8,10,-40])cube([2,10, 40]); 34 | 35 | -------------------------------------------------------------------------------- /3dprinting/ratButton/Readme.md: -------------------------------------------------------------------------------- 1 | # Rat 'button' for jugular catheter 2 | This is an improved version of the implant for jugular catheter originally described in our Front Behav Neurosci paper . 3 | The 'mesh' like base makes it much more stable than the previous version. 4 | -------------------------------------------------------------------------------- /3dprinting/ratButton/ratButton.scad: -------------------------------------------------------------------------------- 1 | $fn=60; 2 | 3 | module button(){ 4 | difference() { 5 | //cylinder(r=10, h=.6) ; // medium thickness 6 | cylinder(r=10, h=.4) ; // think thickness 7 | // #translate([0,0,0]) cylinder(r1=8, r2=7, h=0.5) ; // base 8 | 9 | 10 | for (a=[1:8]){ 11 | rotate([0,0,a*45])translate([5,5,0]) #cylinder(r=1, h=2, center=true); // hole 12 | 13 | } 14 | } 15 | } 16 | 17 | 18 | 19 | module groove(){ 20 | z=1; 21 | w=1.2; 22 | cube([80,w,z], center=true); 23 | for (a=[1:3]){ 24 | translate([0,-a*3,0]) cube([80,w,z], center=true); 25 | translate([0,a*3,0]) cube([80,w,z], center=true); 26 | } 27 | } 28 | 29 | 30 | module base(){ 31 | difference() { 32 | union(){ 33 | cylinder(r=10, h=1) ; // base 34 | translate([0,0,1]) cylinder(r1=10, r2=7, h=0.5) ; // base 35 | } 36 | translate([0,0,0]) 37 | union(){ 38 | cylinder(r1=3, r2=0.68, h=1); //bottom cone 39 | scale([0.5,1,0.5]) rotate([0,0,45]) cube([20,16,0.7]); 40 | groove(); 41 | rotate([0,0,90]) translate([0,0,1.5]) groove(); 42 | x=4.5; 43 | y=4.5; 44 | r=1; 45 | for (a=[0:8]){ 46 | rotate([0,0,45*a])translate([x,-y,0]) cylinder(r=1.5, h=12, center=true); // hole 47 | rotate([0,0,45*a])translate([-x,y,0]) cylinder(r=1.5, h=12, center=true); // hole 48 | } 49 | } 50 | } 51 | 52 | } 53 | 54 | difference(){ 55 | union(){ 56 | //scale([1,1,1]) 57 | base(); 58 | translate([0,0,0.3])cylinder(r=2.8, h=12) ; // stem above the base 59 | //#translate([0,0,0.5])cylinder(r2=4, r1=6.1, h=1) ; // Qin's suggestion 60 | translate([0,0,6])cylinder(r=5, h=9); // top above the base 61 | translate([0,0,4])cylinder(r2=5, r1=3, h=2); // top above the base 62 | 63 | } 64 | translate([0,0,8])cylinder(r=1.55, r2=1.65, h=7); // spring connector, i.e. center cone 65 | 66 | cylinder(r=0.66, h=30, center=true); // center hole 67 | } 68 | -------------------------------------------------------------------------------- /3dprinting/ratButton/ratButton.scad_original: -------------------------------------------------------------------------------- 1 | $fn=100; 2 | 3 | module groove(){ 4 | x=4; 5 | y=4; 6 | translate([-x,y,0]) cylinder(r=1, h=10, center=true); // hole 7 | translate([x,-y,0]) cylinder(r=1, h=10, center=true); // hole 8 | z=1; 9 | w=1.2; 10 | cube([80,w,z], center=true); 11 | translate([0,-3,0]) cube([80,w,z], center=true); 12 | translate([0,3,0]) cube([80,w,z], center=true); 13 | translate([0,-6,0]) cube([80,w,z], center=true); 14 | translate([0,-9, 0]) cube([80,w,z], center=true); 15 | translate([0,6,0]) cube([80,w,z], center=true); 16 | translate([0,9, 0]) cube([80,w,z], center=true); 17 | } 18 | 19 | module button(){ 20 | difference() { 21 | union(){ 22 | cylinder(r=1.95, h=18) ; // stem 23 | cylinder(r=8, h=1) ; // base 24 | translate([0,0,1]) cylinder(r1=8, r2=7, h=0.5) ; // base 25 | cylinder(r=1.4, h=21) ; // spring connector 26 | translate([0,0,21]) cylinder(r1=1.4, r2=1, h=1.5); // tip 27 | } 28 | translate([0,0,-0.01]) 29 | union(){ 30 | cylinder(r1=3, r2=0.68, h=1); //bottom cone 31 | scale([0.5,1,1]) rotate([0,0,45]) cube([20,10,0.7]); 32 | groove(); 33 | rotate([0,0,90]) translate([0,0,1.4]) groove(); 34 | rotate([0,0,-45])translate([4,4,1]) cylinder(r=1, h=2, center=true); // hole 35 | rotate([0,0,-225])translate([4,4,1]) cylinder(r=1, h=2, center=true); // hole 36 | } 37 | } 38 | 39 | } 40 | 41 | module suture(){ 42 | difference(){ 43 | hull(){ 44 | translate([0,2,3.1]) rotate([0,90,0]) cylinder(r0=1,h=2, center=true); 45 | translate([0,4.5,3.1]) rotate([0,90,0]) cylinder(r0=1,h=2, center=true); 46 | translate([-1,2,0.7])cube([2,3.4,3], cente=true); 47 | } 48 | translate([-3,2,0.7])cube([5,2.3,2.1], cente=true); 49 | } 50 | 51 | } 52 | 53 | 54 | difference(){ 55 | union(){ 56 | button(); 57 | suture(); 58 | rotate([0,0,180]) suture(); 59 | translate([0,0,1]) cylinder(r=2.5, h=7) ; // larger stem above the base 60 | } 61 | cylinder(r=0.68, h=30); // center hole 62 | } 63 | -------------------------------------------------------------------------------- /3dprinting/rat_eartag/rat_eartag.scad: -------------------------------------------------------------------------------- 1 | $fn=50; 2 | 3 | module inside_ear(){ 4 | scale([0.8,0.8,1.1]) 5 | difference(){ 6 | sphere(r=4.5); 7 | sphere(r=3.7); 8 | cylinder(h=10,r=1.4, center=true); 9 | } 10 | difference(){ 11 | translate([0,0,-0.5])cylinder(h=0.5, r=3.6,center=false); 12 | translate([1,0,0])cube([4,8,3], center=true); 13 | } 14 | } 15 | 16 | module back_of_ear(){ 17 | difference(){ 18 | union(){ 19 | scale([1,1,0.9])sphere(r=4.5); 20 | translate([0,0,4])cylinder(r=3.2,h=3, center=true); 21 | } 22 | sphere(r=3.5); 23 | cylinder(h=13,r=1.4, center=true); 24 | translate([0,0,5.4]) cube([1.30,7,4], center=true); // top cut 25 | } 26 | //} 27 | // translate([1.2,0,4.7])rotate([90,0,0])difference(){ // notch 28 | // cylinder(h=1,r=0.8, center=true); 29 | // translate([0,-1,0]) cube([2,2,4], center=true); 30 | } 31 | 32 | 33 | difference(){ 34 | union(){ 35 | back_of_ear(); 36 | translate([12,0,0]) inside_ear(); 37 | } 38 | translate([0,0,-5]) cube([40,9,9], center=true); 39 | } 40 | 41 | -------------------------------------------------------------------------------- /3dprinting/steps4ElevatedPlusMaze/plusmaze_openfield_corner_fasterner.scad: -------------------------------------------------------------------------------- 1 | 2 | $fn=40; 3 | 4 | totalW=100; 5 | totalH=100; 6 | 7 | 8 | difference(){ 9 | cube([totalW, totalW, totalH]); 10 | cube([totalW*0.70, totalW*0.70, totalH*1.2]); 11 | } 12 | -------------------------------------------------------------------------------- /3dprinting/steps4ElevatedPlusMaze/plusmazeboots.scad: -------------------------------------------------------------------------------- 1 | // this boot further increases the height of the plus maze so that it can be placed in the openfield and not worry about the open arm is close to the wall of the open field. 2 | 3 | $fn=100; 4 | 5 | module hollow(w1, w2,h){ 6 | difference(){ 7 | cube([w1, w1, h], center=true); 8 | cube([w2, w2, h], center=true); 9 | } 10 | 11 | } 12 | 13 | 14 | module space(w, h){ 15 | w1=10; 16 | gap=20; 17 | for (i = [1:6]) { 18 | translate([gap*i,0,0]) cube([w1,w,h]); 19 | } 20 | } 21 | 22 | 23 | difference(){ 24 | hollow(152,142,100); 25 | translate([0,0,50]) cube([142, 142, 20], center=true); 26 | difference(){ 27 | cylinder (r=110, h=100, center=true); 28 | cylinder(r=104, h=100,center=true, $fs=0.2); 29 | } 30 | // reduce the printing time 31 | translate([-75, 140/2, -40]) space(10,80); 32 | rotate([0,0,90])translate([-75, 140/2, -40]) space(10,80); 33 | rotate([0,0,180])translate([-75, 140/2, -40]) space(10,80); 34 | rotate([0,0,270])translate([-75, 140/2, -40]) space(10,80); 35 | translate([0,0,-50])rotate([90,0,90]) scale([1,0.1,1]) cylinder(r=55, h=160, center=true); 36 | translate([0,0,-50])rotate([90,0,180])scale([1,0.1,1]) cylinder(r=55, h=160, center=true); 37 | 38 | } 39 | 40 | difference(){ 41 | translate([0,0,-3.2]) rotate([0,0,45]) hollow(107,100,100-6.4); 42 | // further reduce print time 43 | translate([0,0,-50])rotate([90,0,45]) cylinder(r=45, h=120, center=true); 44 | translate([0,0,-50])rotate([90,0,135]) cylinder(r=45, h=120, center=true); 45 | } 46 | 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenBehavior 2 | 3 | This project aims to establish a computing platform for rodent behavior research using the Raspberry Pi computer. We are building devices for conducting operant conditioning, as well as some infrared sensor based assays. We also designed an environmental sensor set that records the temperature, humidity, air pressure, ambient light, noise level, etc. 4 | 5 | These projects are in various stages of development. The following are the most mature projects. 6 | 7 | ## Operant Licking 8 | This project develops a home cage device for operant licking (fixed ratio, various ratio, or progressive ratio schedules). Detailed description of this project is published in a [PeerJ article]( https://peerj.com/articles/2981/) 9 | 10 | 11 | ## EnvSensors 12 | 13 | This device collects four environmental variables and we have several of them running in the lab. This device is also described in our [PeerJ article](https://peerj.com/articles/2981/) 14 | 15 | ## RFID 16 | 17 | This project develops a standalone RFID reader for the EM4100 implantable glass chips. We use this daily in the lab. 18 | 19 | ## Extinction 20 | 21 | This device is used to run extinction experiments as described by [Wang et al. (2014)](www.ncbi.nlm.nih.gov/PubMed/25532105) 22 | 23 | 24 | ## Motion 25 | 26 | This project adds a motion sensor to standard operant chambers. 27 | 28 | -------------------------------------------------------------------------------- /RFID/RDM630-Spec.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/RFID/RDM630-Spec.pdf -------------------------------------------------------------------------------- /RFID/Rdm6300UART.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ''' 4 | code originally obtained from raspberry pi forum: 5 | http://www.raspberrypi.org/forums/viewtopic.php?t=59025&p=501603 6 | ''' 7 | 8 | import serial 9 | import sys 10 | import time 11 | from operator import xor 12 | # UART 13 | ID = "" 14 | Zeichen = 0 15 | Checksumme = 0 16 | Tag = 0 17 | # Flags 18 | Startflag = "\x02" 19 | Endflag = "\x03" 20 | # UART oeffnen 21 | UART = serial.Serial("/dev/ttyAMA0", 9600) 22 | UART.close(); 23 | UART.open() 24 | while True: 25 | # Variablen loeschen 26 | Checksumme = 0 27 | Checksumme_Tag = 0 28 | ID = "" 29 | # Zeichen einlesen 30 | Zeichen = UART.read() 31 | # Uebertragungsstart signalisiert worden? 32 | if Zeichen == Startflag: 33 | # ID zusammen setzen 34 | for Counter in range(13): 35 | Zeichen = UART.read() 36 | ID = ID + str(Zeichen) 37 | # Endflag aus dem String loeschen 38 | ID = ID.replace(Endflag, "" ) # Checksumme berechnen 39 | for I in range(0, 9, 2): 40 | Checksumme = Checksumme ^ (((int(ID[I], 16)) << 4) + int(ID[I+1], 16)) 41 | Checksumme = hex(Checksumme) 42 | # Tag herausfiltern 43 | Tag = ((int(ID[1], 16)) << 8) + ((int(ID[2], 16)) << 4) + ((int(ID[3], 16)) << 0) 44 | Tag = hex(Tag) 45 | # Ausgabe der Daten 46 | print "------------------------------------------" 47 | print "Datensatz: ", ID 48 | print "Tag: ", Tag 49 | print "ID: ", ID[4:10], " - ", int(ID[4:10], 16) 50 | print "Checksumme: ", Checksumme 51 | print "------------------------------------------" 52 | -------------------------------------------------------------------------------- /RFID/Rdm6300_USB.py: -------------------------------------------------------------------------------- 1 | import time 2 | import serial 3 | import RPi.GPIO as gpio 4 | from operator import xor 5 | 6 | ### This is the USB version 7 | ### The RDM6300 is connected to a CP2102 serial to USB breakout board 8 | ### http://forum.arduino.cc/index.php?topic=138611.0 9 | ### http://www.amazon.com/gp/product/B009T2ZR6W 10 | ### modified from code written by Ivan Amies. 11 | 12 | 13 | # Flags ## DO NOT CHANGE #### 14 | ############################# 15 | Startflag = "\x02" 16 | Endflag = "\x03" 17 | ############################# 18 | 19 | # initial settings for the uart device. Change as necessary, or read in as desired.# 20 | baud_rate = 9600 21 | time_out = 0.05 22 | ### 23 | 24 | def initialize_uart(path_to_sensor) : 25 | uart = serial.Serial(path_to_sensor, baud_rate, timeout = time_out) 26 | uart.close() 27 | uart.open() 28 | uart.flushInput() 29 | uart.flushOutput() 30 | print(path_to_sensor + " initiated") 31 | return uart; 32 | 33 | def readrfid(uart): 34 | while True: 35 | Zeichen = 0 36 | Tag = 0 37 | ID = "" 38 | Zeichen = uart.read() 39 | if Zeichen == Startflag: 40 | for Counter in range(13): 41 | Zeichen = uart.read() 42 | ID = ID + str(Zeichen) 43 | ID = ID.replace(Endflag, "" ) 44 | print "RFID detected: "+ ID 45 | 46 | usb = "/dev/ttyUSB0" 47 | uart = initialize_uart(usb) 48 | readrfid(uart) 49 | 50 | 51 | -------------------------------------------------------------------------------- /RFID/Readme.md: -------------------------------------------------------------------------------- 1 | # Standalone RFID Reader 2 | 3 | This is a simple device that connects an RDM 6300 RFID reader board to the RPi. The ID of the glass tags is shown on the LCD. 4 | 5 | -------------------------------------------------------------------------------- /RFID/Untitled.scad: -------------------------------------------------------------------------------- 1 | module rfid_antenna_housing(){ 2 | difference(){ 3 | cube([53,43,7], center=true); // rfid antenna outside; 4 | translate([3,0,0]) cube([56,37,3.6], center=true); // rfid antenna groove; 5 | cube([39,31,30], center=true); //rfid antenna loop inside 6 | } 7 | } 8 | 9 | rfid_antenna_housing(); -------------------------------------------------------------------------------- /RFID/connections.txt: -------------------------------------------------------------------------------- 1 | RDM 6300 connections 2 | ------------------- 3 | The antenna can be connected in either direction 4 | connect the Tx on the RPi (i.e. pin 8) to Rx on the board (i.e. PIN 2) 5 | connect the Rx on the RPi (i.e. pin 10) to Tx on the board (i.e. PIN 1) 6 | connect the ground on the RPi (i.e. pin 6) to the ground on the board (i.e. Pin 4) 7 | connect the 5V on the RPi (i.e. pin 2) to the power in on the board (i.e. Pin 5) 8 | 9 | LCD connections 10 | -------------- 11 | RS -> Pin 03 / GPIO 02 12 | EN -> Pin 05 / GPIO 03 13 | D7 -> Pin 07 / GPIO 04 14 | D6 -> Pin 11 / GPIO 17 15 | D5 -> Pin 13 / GPIO 27 16 | D4 -> Pin 15 / GPIO 22 17 | 18 | -------------------------------------------------------------------------------- /RFID/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Clone the openbehavior repository to the home directory of user 'pi' and 4 | # then run this script with root permissions to install RFID scanner 5 | 6 | if [ ! -d "/home/pi/Pies" ]; then 7 | mkdir "/home/pi/Pies" 8 | chown pi:users "/home/pi/Pies" 9 | fi 10 | 11 | if [ ! -d "/home/pi/Pies/RFIDReader" ]; then 12 | mkdir "/home/pi/Pies/RFIDReader" 13 | chown pi:users "/home/pi/Pies/RFIDReader" 14 | fi 15 | 16 | cp /home/pi/openbehavior/RFID/rfidscanner.service /etc/systemd/system/rfidscanner.service 17 | systemctl enable rfidscanner.service 18 | 19 | -------------------------------------------------------------------------------- /RFID/rfidReaderCase.scad: -------------------------------------------------------------------------------- 1 | $fn=100; 2 | 3 | module mounting_m25(innR=1.6, h=4){ // screw 4 | difference(){ 5 | color("orange") cylinder(r=3.8, h); 6 | cylinder(r=innR, h=10); 7 | } 8 | } 9 | 10 | module mounting_pi(){ 11 | translate([-58/2,-49/2,0]) mounting_m25(); 12 | translate([58/2,-49/2,0]) mounting_m25(); 13 | translate([-58/2,49/2,0]) mounting_m25(); 14 | translate([58/2,49/2,0]) mounting_m25(); 15 | translate([-10,0,0]) cube([85,56,0.1], center=true); 16 | } 17 | 18 | module rfid_antenna_housing(){ 19 | difference(){ 20 | cube([53,40,10], center=true); // rfid antenna outside; 21 | translate([0,-6,0]) cube([47,46,5], center=true); // rfid antenna groove; 22 | cube([36,25,18], center=true); //rfid antenna loop inside 23 | } 24 | } 25 | 26 | module lcdPanel(){ 27 | w=75; 28 | l=31; 29 | difference(){ 30 | union(){ 31 | translate([w/2, l/2,0])cylinder(r=3.6, h=10); 32 | translate([w/2, -l/2,0])cylinder(r=3.6, h=10); 33 | translate([-w/2, -l/2,0])cylinder(r=3.6, h=10); 34 | translate([-w/2, l/2,0])cylinder(r=3.6, h=10); 35 | 36 | } 37 | union (){ 38 | translate([w/2, l/2,0])cylinder(r=1.6, h=11); 39 | translate([w/2, -l/2,0])cylinder(r=1.6, h=11); 40 | translate([-w/2, -l/2,0])cylinder(r=1.6, h=11); 41 | translate([-w/2, l/2,0])cylinder(r=1.6, h=11); 42 | } 43 | } 44 | 45 | } 46 | 47 | module baseboard(){ 48 | difference(){ 49 | color("grey") translate([0,-96,-3]) cube([90, 152, 4], center=true); // base board 50 | translate([40,-105,-2])cube([3.0, 11.5,5], center=true); // rfid board connection via the pins; 51 | translate([0,-6,0]) cube([47,46,5], center=true); // rfid antenna groove; 52 | } 53 | } 54 | module sidewall(){ 55 | color("blue") cube([2,100,30], center=true); 56 | translate([3,46.5,8]) difference( ) { cube([7,7,14], center=true); cylinder(r=1.9, h=43);} 57 | translate([3,-46.5,8]) difference( ) { cube([7,7,14], center=true); cylinder(r=1.9, h=43);} 58 | } 59 | 60 | 61 | module topCoverMounting() { 62 | mx=41; 63 | my=-73.3; 64 | my2=-166.6; 65 | color("blue") translate([mx,my,0]) cylinder(r=1.8,h=40); 66 | color("blue") translate([-mx,my,0]) cylinder(r=1.8,h=40); 67 | color("blue") translate([-mx,my2,0])cylinder(r=1.8,h=40); 68 | color("blue") translate([mx,my2,0]) cylinder(r=1.8,h=40); 69 | } 70 | 71 | module topCover(){ 72 | difference(){ 73 | translate([0,-120,30]) cube([90, 104, 3], center=true); 74 | topCoverMounting(); 75 | } 76 | } 77 | 78 | module lcd(){ // model: HD44780 79 | translate([0,-44, 13.1]) cube([69+1, 24+1, 8.4], center=true); 80 | translate([0,-44, 13.1-3.7]) cube([80.6, 36, 1], center=true); 81 | } 82 | 83 | module screws_frontCover(){ 84 | r0=1.6; 85 | h0=25; 86 | // in the base 87 | translate([40,-67,-20]) cylinder(r=r0, h0); 88 | translate([-40,-67,-20]) cylinder(r=r0, h0); 89 | // on the side 90 | h1=10; 91 | translate([41,-67,20]) rotate([90,0,0]) cylinder(r=r0, h1); 92 | translate([-41,-67,20]) rotate([90,0,0]) cylinder(r=r0, h1); 93 | } 94 | 95 | module frontCover (){ 96 | difference() { 97 | union(){ 98 | translate([-45,-70,-1]) color("pink") cube([2,50,16]); 99 | translate([45-2,-70,-1]) color("pink") cube([2,50,16]); 100 | translate([-45,-22,-1]) color("pink") cube([90, 2,16]); 101 | translate([-45,-70,15]) color("blue") cube([90, 50,2]); 102 | translate([-45,-70,13]) cube ([90,2,15]); 103 | translate([-40,-67,6]) cube([6,6,14],center=true); // for screws 104 | translate([40,-67,6]) cube([6,6,14],center=true); // for screws 105 | } 106 | lcd(); 107 | translate([-27,-69,10]) cylinder(r=5,h=6); // brightness adjust 108 | screws_frontCover(); 109 | } 110 | } 111 | 112 | union(){ 113 | // lcd(); 114 | difference() { 115 | union(){ 116 | rfid_antenna_housing(); 117 | translate([0,-43,-1]) lcdPanel(); 118 | translate([-13,-143+8,-1.0]) rotate([0,0,-90]) mounting_pi(); // pi // rpi 119 | bx=44; 120 | by=-120; 121 | baseboard(); 122 | translate([bx,by,13]) rotate([0,0,180]) sidewall(); 123 | translate([-bx,by,13]) sidewall(); 124 | } 125 | screws_frontCover(); 126 | } 127 | difference(){ 128 | translate([0,-171,13]) cube([90,2,30], center=true);// backwall 129 | translate([-13,-170,3]) cube([20,10, 5], center=true); // sdcard slot 130 | translate([35,-170, 28]) rotate([90,0,0]) cylinder(r=2.5, h=20); 131 | } 132 | } 133 | topCover(); 134 | frontCover(); 135 | 136 | 137 | -------------------------------------------------------------------------------- /RFID/rfidscanner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import serial 4 | import sys 5 | import time 6 | import datetime 7 | import operator 8 | import Adafruit_CharLCD 9 | 10 | # CONSTANTS 11 | # path to data file 12 | 13 | idfile=open("/home/pi/deviceid") 14 | device=idfile.read() 15 | device=device.strip() 16 | today=datetime.date.today() 17 | td=str(today)+"\n" 18 | year=datetime.date.today().year 19 | month=datetime.date.today().month 20 | datafile="/home/pi/Pies/RFIDReader/"+device+"_"+str(year)+"-"+str(month)+".log" 21 | # flags 22 | startflag = "\x02" 23 | endflag = "\x03" 24 | 25 | def printIDtoLCD(lcd, idstring): 26 | lcd.clear() 27 | lcd.message(td) 28 | lcd.message("Tag Found!\n") 29 | time.sleep(.5) 30 | lcd.clear() 31 | lcd.message(idstring) 32 | 33 | def main(): 34 | # UART data 35 | idstring = "" 36 | chardata = 0 37 | 38 | # initialize the LCD 39 | lcd = Adafruit_CharLCD.Adafruit_CharLCD() 40 | lcd.begin(16,1) 41 | lcd.clear() 42 | lcd.message("a posse ad esse\n") 43 | lcd.message(td) 44 | time.sleep(2) 45 | 46 | # open the reader through UART 47 | UART = serial.Serial("/dev/ttyAMA0", 9600) 48 | UART.close() 49 | UART.open() 50 | 51 | # Instruct the user that the scanner is ready to read 52 | lcd.clear() 53 | lcd.message("Ready to scan!") 54 | 55 | # time of scan 56 | firstsaw={} 57 | # Main program loop 58 | while True: 59 | time.sleep(0.25) 60 | # zero out the variables 61 | tag = 0 62 | idstring = "" 63 | # read in a character 64 | chardata = UART.read() 65 | # Is it the start flag? 66 | if chardata == startflag: 67 | # concatenate id together 68 | for i in range(12): 69 | chardata = UART.read() 70 | idstring = idstring + str(chardata) 71 | if idstring not in firstsaw: 72 | firstsaw[idstring]=time.time() 73 | lapsed=int((time.time()-firstsaw[idstring])/60) 74 | msg=idstring + "\n"+ "Seen "+ str(lapsed) + " m ago" 75 | printIDtoLCD(lcd, msg) 76 | with open(datafile, "a") as f: 77 | f.write(time.strftime("%Y-%m-%d\t%H:%M:%S\t") + idstring + "\n") 78 | f.close() 79 | UART.flushInput() 80 | 81 | main() 82 | -------------------------------------------------------------------------------- /RFID/rfidscanner.service: -------------------------------------------------------------------------------- 1 | # systemd unit for starting RFID scanner on boot 2 | [Unit] 3 | Description=RFIDscanner 4 | 5 | [Service] 6 | Type=simple 7 | ExecStart=/home/pi/openbehavior/RFID/rfidscanner.py 8 | ExecStop=/usr/bin/pkill rfidscanner.py 9 | 10 | [Install] 11 | WantedBy=getty.target 12 | DefaultInstance=tty1 13 | -------------------------------------------------------------------------------- /RFID/settingUpUART.readme: -------------------------------------------------------------------------------- 1 | For Raspbian Jessie: 2 | run the following two commands 3 | 4 | sudo systemctl stop serial-getty@ttyAMA0.service 5 | sudo systemctl disable serial-getty@ttyAMA0.service 6 | 7 | then disable the login shell: 8 | 9 | sudo raspi-config 10 | 11 | select 9 for advanced options. 12 | select A8 for Serial to disable login shell. 13 | 14 | then reboot. 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /RFID_eInk_Reader/Readme.md: -------------------------------------------------------------------------------- 1 | # This is a RFID reader with an eInk hat display 2 | 3 | ## 2.7 inch e-paper hat 4 | * From [WaveShare.com](https://www.waveshare.com/2.7inch-e-Paper-HAT.htm) 5 | * User manual in [PDF](https://www.waveshare.com/w/upload/3/31/2.7inch_e-paper_hat_user_manual_en.pdf) 6 | 7 | ## RFID USB reader 8 | * https://www.amazon.com/Reader-LANMU-125khz-Contactless-Proximity/dp/B07B7H6CQ2 9 | 10 | ## Software 11 | * Library https://github.com/waveshare/e-Paper/tree/master/2.7inch_e-paper_code/RaspberryPi/ 12 | * Steps not described in the user manual 13 | * enable SPI interface in the PI ```sudo raspi-config``` 14 | * For the python demo code from waveshare, make sure the font is present in your system. 15 | * To run the python code automatically after boot, do the following 16 | * change the boot into command line and enable auto login with user pi by running ```sudo raspi-config``` 17 | * add the python program to the end of the .bashrc file for user pi 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /RFID_eInk_Reader/a_rfid.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding:utf-8 -*- 3 | 4 | #import epd2in7 5 | import time 6 | #from PIL import Image,ImageDraw,ImageFont 7 | import os 8 | 9 | 10 | #epd = epd2in7.EPD() 11 | #epd.init() 12 | #epd.Clear(0xFF) 13 | 14 | def show(text): 15 | # Himage = Image.new('1', (epd2in7.EPD_HEIGHT, epd2in7.EPD_WIDTH), 255) # 255: clear the frame 16 | # draw = ImageDraw.Draw(Himage) 17 | # font32 = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf',32) 18 | # draw.text((10, 0), text, font = font32, fill = 0) 19 | # epd.display(epd.getbuffer(Himage)) 20 | print(text) 21 | 22 | print("Ready to scan") 23 | line="" 24 | cnt=0 25 | while True: 26 | if (cnt == 5 ): 27 | cnt=0 28 | line="" 29 | cnt=cnt+1 30 | rfid=input("Waiting for RFID") 31 | #rfid=hex(int(rfid)).upper() 32 | l=len(rfid) 33 | line=line + rfid[2:l-4] + "." + rfid[-4:] + "\n" 34 | print(line) 35 | time.sleep(.5) 36 | 37 | -------------------------------------------------------------------------------- /RFID_eInk_Reader/rfid_reader_eink.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding:utf-8 -*- 3 | 4 | import epd2in7 5 | import time 6 | from PIL import Image,ImageDraw,ImageFont 7 | import os 8 | 9 | 10 | epd = epd2in7.EPD() 11 | epd.init() 12 | epd.Clear(0xFF) 13 | 14 | def show(text): 15 | Himage = Image.new('1', (epd2in7.EPD_HEIGHT, epd2in7.EPD_WIDTH), 255) # 255: clear the frame 16 | draw = ImageDraw.Draw(Himage) 17 | font32 = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf',32) 18 | draw.text((10, 0), text, font = font32, fill = 0) 19 | epd.display(epd.getbuffer(Himage)) 20 | 21 | show("Ready to scan") 22 | line="" 23 | cnt=0 24 | while True: 25 | if (cnt == 5 ): 26 | cnt=0 27 | line="" 28 | cnt=cnt+1 29 | rfid=input("Waiting for RFID") 30 | rfid=rfid.upper() 31 | l=len(rfid) 32 | line=line + rfid[0:l-4] + "." + rfid[-4:] + "\n" 33 | show(line) 34 | time.sleep(.5) 35 | 36 | epd.sleep() 37 | -------------------------------------------------------------------------------- /RFID_eInk_Reader/rfid_reader_eink.scad: -------------------------------------------------------------------------------- 1 | $fn=100; 2 | 3 | module mounting_m25(innR=1.6, h=4){ // screw 4 | difference(){ 5 | color("orange") cylinder(r=3.8, h); 6 | cylinder(r=innR, h=10); 7 | } 8 | } 9 | 10 | module mounting_pi(){ 11 | translate([-58/2,-49/2,0]) mounting_m25(); 12 | translate([58/2,-49/2,0]) mounting_m25(); 13 | translate([-58/2,49/2,0]) mounting_m25(); 14 | translate([58/2,49/2,0]) mounting_m25(); 15 | translate([-10,0,0]) cube([85,56,0.1], center=true); 16 | } 17 | 18 | 19 | 20 | module baseboard(){ 21 | color("grey")cube([70, 93, 3], center=true); // base board 22 | } 23 | module sidewall(){ // include the top cover mounting holes 24 | color("blue") cube([2,93,27], center=true); 25 | translate([3, 43,10]) difference( ) { cylinder(r=3.5, h=5, center=true); cylinder(r=1.6, h=43);} 26 | translate([3,-43,10]) difference( ) { cylinder(r=3.5, h=5, center=true); cylinder(r=1.6, h=43);} 27 | } 28 | 29 | 30 | module topCoverMounting() { 31 | mx=31; 32 | my=-31.5; 33 | my2=54.5; 34 | color("blue") translate([mx,my,0]) cylinder(r=1.9,h=40); 35 | color("blue") translate([-mx,my,0]) cylinder(r=1.9,h=40); 36 | color("blue") translate([-mx,my2,0])cylinder(r=1.9,h=40); 37 | color("blue") translate([mx,my2,0]) cylinder(r=1.9,h=40); 38 | } 39 | 40 | module epaper(){ 41 | translate([-18,-24,0]) cube([40, 60, 30]); 42 | } 43 | 44 | module header(){ 45 | translate([-30,-26,25.5]) cube([10,60,2]); 46 | } 47 | 48 | module topCover(){ 49 | difference(){ 50 | color("green")translate([0,11.5,27]) cube([70, 93, 3], center=true); 51 | topCoverMounting(); 52 | epaper(); 53 | header(); 54 | } 55 | } 56 | 57 | module case(){ 58 | union(){ 59 | difference() { 60 | union(){ 61 | rotate([0,0,-90]) translate([0,0,1])mounting_pi(); // pi // rpi 62 | translate([0,11.5,1]) baseboard(); 63 | bx=34; 64 | by=11.5; 65 | translate([bx,by,13]) rotate([0,0,180]) sidewall(); 66 | translate([-bx,by,13]) sidewall(); 67 | } 68 | translate([30,-30, 4]) cube([10, 15, 9]); // power plug 69 | } 70 | difference(){ // short end 71 | translate([0,-34,13]) cube([70,2,27], center=true);// backwall 72 | translate([0,-34,4]) cube([20,10, 6], center=true); // sdcard slot 73 | translate([-18,-34,6]) rotate([90,0,0]) cylinder(r=3,h=5, center=true); // view port for LEDs 74 | 75 | } 76 | difference(){ // USB end 77 | translate([0,57,13]) cube([70,2,27], center=true);// backwall 78 | translate([-10,56,18]) cube([35,20,25], center=true); // USB 79 | } 80 | } 81 | } 82 | 83 | module rfidholder(){ 84 | difference() { 85 | cube ([74, 80, 17],center=true); //outside 86 | cube ([66, 130,40],center=true); // middle 87 | translate([0,0,-2])cube ([70, 100,13],center=true); //inner most 88 | } 89 | } 90 | 91 | 92 | //case(); 93 | 94 | topCover(); 95 | //translate([0,10,34])rfidholder(); 96 | 97 | -------------------------------------------------------------------------------- /RFID_eInk_Reader/rfid_reader_eink_cover.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/RFID_eInk_Reader/rfid_reader_eink_cover.stl -------------------------------------------------------------------------------- /RPI.PinLables.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/RPI.PinLables.pdf -------------------------------------------------------------------------------- /envSensors/3D_design_frame/envSensorBoard.scad: -------------------------------------------------------------------------------- 1 | $fn=60; 2 | 3 | translate([-4,0,0]) pi(); 4 | translate([-65,-100,0]) base(); 5 | translate([-60,-65,0]) color("red") devboard(); 6 | translate([-2,-35,0]) rtc(); 7 | translate([13,-94,0]) humidity(); 8 | color("green") translate([-22,-94,0]) lux(); 9 | color("cyan") translate([-56,-94,0]) barometer(); 10 | 11 | module barometer(){ 12 | m25(innR=1.1); 13 | translate([12,0,0]) m25(innR=1.1); 14 | } 15 | 16 | module humidity(){ 17 | m25(innR=1.1); 18 | translate([11,0,0]) m25(innR=1.1); 19 | } 20 | 21 | module lux(){ 22 | m25(innR=1.1); 23 | translate([13.5,0,0]) m25(innR=1.1); 24 | } 25 | 26 | 27 | module devboard() { 28 | translate([4,4,0]) m25(); 29 | translate([44,4,0]) m25(); 30 | translate([4,26,0]) m25(); 31 | translate([44,26,0]) m25(); 32 | } 33 | 34 | module rtc(){ 35 | m25(innR=1.3); 36 | difference(){ 37 | union(){ 38 | translate([22.5,0,0]) cylinder(r=3.8, h=7); 39 | translate([24.5,0,0]) cylinder(r=3.8, h=7) ; 40 | } 41 | translate([22.5,0,0]) cylinder(r=1.2, h=10); 42 | translate([24.5,0,0]) cylinder(r=1.2, h=10); 43 | } 44 | } 45 | 46 | 47 | module m25(innR=1.6, h=7){ // screw 48 | difference(){ 49 | color("orange") cylinder(r=3.8, h); 50 | cylinder(r=innR, h=10); 51 | } 52 | } 53 | 54 | module pi(){ 55 | translate([-58/2,-49/2,0]) m25(); 56 | translate([58/2,-49/2,0]) m25(); 57 | translate([-58/2,49/2,0]) m25(); 58 | translate([58/2,49/2,0]) m25(); 59 | // translate([-10,0,0]) cube([85,56,0.1], center=true); 60 | } 61 | 62 | module base(){ 63 | color("grey") cube([100,130,2]); 64 | } 65 | 66 | 67 | -------------------------------------------------------------------------------- /envSensors/HTU21DF.py: -------------------------------------------------------------------------------- 1 | # Raspberry Pi Driver for Adafruit HTU21D-F 2 | # Go buy one at https://www.adafruit.com/products/1899 3 | # written by D. Alex Gray dalexgray@mac.com 4 | # Thanks to egutting at the adafruit.com forums 5 | # Thanks to Joan on the raspberrypi.org forums 6 | # This requires the pigpio library 7 | # Get pigpio at http://abyz.co.uk/rpi/pigpio/index.html 8 | # 9 | # Copyright (c) 2014 D. Alex Gray 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy 11 | # of this software and associated documentation files (the "Software"), to deal 12 | # in the Software without restriction, including without limitation the rights 13 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | # copies of the Software, and to permit persons to whom the Software is 15 | # furnished to do so, subject to the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be included in 18 | # all copies or substantial portions of the Software. 19 | # 20 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | # THE SOFTWARE. 27 | import time 28 | import pigpio 29 | import math 30 | 31 | pi = pigpio.pi() 32 | 33 | # HTU21D-F Address 34 | addr = 0x40 35 | 36 | # i2c bus, if you have a Raspberry Pi Rev A, change this to 0 37 | bus = 1 38 | 39 | # HTU21D-F Commands 40 | rdtemp = 0xE3 41 | rdhumi = 0xE5 42 | wtreg = 0xE6 43 | rdreg = 0xE7 44 | reset = 0xFE 45 | 46 | def htu_reset(): 47 | handle = pi.i2c_open(bus, addr) # open i2c bus 48 | pi.i2c_write_byte(handle, reset) # send reset command 49 | pi.i2c_close(handle) # close i2c bus 50 | time.sleep(0.2) # reset takes 15ms so let's give it some time 51 | 52 | def read_temperature(): 53 | handle = pi.i2c_open(bus, addr) # open i2c bus 54 | pi.i2c_write_byte(handle, rdtemp) # send read temp command 55 | time.sleep(0.055) # readings take up to 50ms, lets give it some time 56 | (count, byteArray) = pi.i2c_read_device(handle, 3) # vacuum up those bytes 57 | pi.i2c_close(handle) # close the i2c bus 58 | t1 = byteArray[0] # most significant byte msb 59 | t2 = byteArray[1] # least significant byte lsb 60 | temp_reading = (t1 * 256) + t2 # combine both bytes into one big integer 61 | temp_reading = math.fabs(temp_reading) # I'm an idiot and can't figure out any other way to make it a float 62 | temperature = ((temp_reading / 65536) * 175.72 ) - 46.85 # formula from datasheet 63 | return temperature 64 | 65 | def read_humidity(): 66 | handle = pi.i2c_open(bus, addr) # open i2c bus 67 | pi.i2c_write_byte(handle, rdhumi) # send read humi command 68 | time.sleep(0.055) # readings take up to 50ms, lets give it some time 69 | (count, byteArray) = pi.i2c_read_device(handle, 3) # vacuum up those bytes 70 | pi.i2c_close(handle) # close the i2c bus 71 | h1 = byteArray[0] # most significant byte msb 72 | h2 = byteArray[1] # least significant byte lsb 73 | humi_reading = (h1 * 256) + h2 # combine both bytes into one big integer 74 | humi_reading = math.fabs(humi_reading) # I'm an idiot and can't figure out any other way to make it a float 75 | uncomp_humidity = ((humi_reading / 65536) * 125 ) - 6 # formula from datasheet 76 | # to get the compensated humidity we need to read the temperature 77 | temperature = read_temperature() 78 | humidity = ((25 - temperature) * -0.15) + uncomp_humidity 79 | return humidity 80 | 81 | if __name__ == "__main__": 82 | while 1: 83 | temp=read_temperature() 84 | humd=read_humidity() 85 | print (temp, humd) 86 | time.sleep(2) 87 | -------------------------------------------------------------------------------- /envSensors/Readme.md: -------------------------------------------------------------------------------- 1 | # Using the Raspberry Pi single board computer to monitor the lab environment 2 | 3 | The sensor we use include the HTU21DF for humidity, TSL2561 for light, and BMP180 for barometric pressure. Both the HTU21DF and BMP180 have a temperature sensor. So we take the average readout of the two. These sensors are all connected to the Raspberry Pi via I2C. We also use a I2C real-time clock (DS1307 from either Adafruit or JBtek. JBtek is cheaper but some of the units we got were not reliable) to ensure the accuracy of the time. 4 | 5 | The location of the device is identified in a file named deviceid located at /home/pi/. The ID stored in this file is used to name the data file. This ID is also entered in the data file. This allows the same program to be deployed at multiple locations. The python logger program is run once every 10 min via cron. 6 | 7 | We use this device to monitor the environment of animal housing rooms where the light cycle is reversed. The logger program writes the lux level during the night to a file called lux.csv. The checklux.py program, also ran via a cron job, checks the lux level during the day and flashes an LED to alert the technician if lights are off during the night. 8 | 9 | ## Parts list 10 | 11 | Raspberry Pi 2B or 3 [Element 14] (https://www.element14.com/community/community/raspberry-pi) 12 | 13 | TSL2561 Lux Sensor [Adafruit] (https://www.adafruit.com/products/439) 14 | 15 | BMP180 Pressure Sensor [Adafruit] (https://www.adafruit.com/products/1603) 16 | 17 | HTU21D-F Humidity Sensor [Adafruit] (https://www.adafruit.com/products/1899) 18 | 19 | SB4 Snappable PC BreadBoard [Amazon] (https://www.amazon.com/gp/product/B00PX52C7Q) 20 | 21 | 1P-1P female to Female Jump Wire [Amazon] (https://www.amazon.com/gp/product/B00R96X8JS) 22 | 23 | Edimax USB WiFi module, not needed if use RPi 3B [Amazon] (https://www.amazon.com/Edimax-EW-7811Un-150Mbps-Raspberry-Supports/dp/B003MTTJOY/) 24 | 25 | ## Assembly 26 | 27 | ### Add wires to the sensors 28 | 29 | Cut the jumper wire in half. Solder four wires to each sensor (and RTC). We use black (or grey) for ground, red (or orange) for 5V, blue for SCL, and green for SDA.  30 | 31 | 32 | ### Prepare the breadboard 33 | Drill four holes at the corners. Solder four rows of pin heads (five pins each) to the snappable breadboard. 34 | We use the two side rows for the GND and 5V. Use the middle two rows for SDA and SCL. 35 | . 36 | 37 | Make sure pins on the same head are all connected at the back. (You can solder a short segment of wire to two middle pin heads to connect them). 38 | . 39 | 40 | ### Connect the wires 41 | 42 | Connect the sensors and the real-time clock to the pins. 43 |  44 | 45 | Use one additional sets of four wires to connect the last set of pins to the GND, 5V, SCL, and SDA pins on the RPi. 46 | 47 | ### Final step 48 | 49 | Screw the parts to the 3D printed base. 50 |  51 | 52 | ## Software 53 | 54 | Clone the repository 55 | ``` 56 | cd /home/pi/ 57 | git clone https://github.com/chen42/openbehavior.git 58 | ``` 59 | 60 | Enable the realtime clock by following these [instructions](https://learn.adafruit.com/adding-a-real-time-clock-to-raspberry-pi/overview) 61 | 62 | Edit the /etc/rc.local file to include the following lines (needed by the RTC and HTU21D-F sensor library) 63 | 64 | ``` 65 | echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device 66 | pigpiod & 67 | ``` 68 | 69 | Run the following command to edit cron 70 | 71 | ``` 72 | sudo crontab -e 73 | ``` 74 | 75 | Add the following line will run the EnvSensor script once every 20 min. 76 | 77 | ``` 78 | */20 * * * python /home/pi/openbehavior/envSensors/env_logger.cron.py 79 | ``` 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /envSensors/SampleData.tab: -------------------------------------------------------------------------------- 1 | 2015-09-23 14:50:03 HSRatsIVSARoom 20.0444042969 65.3711937256 100982 0.0 2 | 2015-09-23 15:00:03 HSRatsIVSARoom 20.1265795898 66.8091518555 100982 0.0 3 | 2015-09-23 15:10:03 HSRatsIVSARoom 20.1319421387 66.8794251709 100977 0.0 4 | 5 | -------------------------------------------------------------------------------- /envSensors/bmp.py: -------------------------------------------------------------------------------- 1 | 2 | import time 3 | import Adafruit_BMP.BMP085 as BMP085 4 | 5 | 6 | barometer = BMP085.BMP085(mode=BMP085.BMP085_ULTRAHIGHRES) 7 | while 1: 8 | pressure=barometer.read_pressure() 9 | temp=barometer.read_temperature() 10 | print (str(temp), str(pressure)) 11 | time.sleep(2) 12 | 13 | -------------------------------------------------------------------------------- /envSensors/checklux.py: -------------------------------------------------------------------------------- 1 | # Abigail Salinero, a summer student, contributed this code. 2 | 3 | import RPi.GPIO as GPIO 4 | import time 5 | 6 | pin=11 7 | GPIO.setmode(GPIO.BOARD) 8 | GPIO.setup(pin, GPIO.OUT) 9 | 10 | 11 | def blink(pin): 12 | GPIO.output(pin,GPIO.HIGH) 13 | time.sleep(.2) 14 | GPIO.output(pin,GPIO.LOW) 15 | time.sleep(.2) 16 | return 17 | 18 | 19 | sum = 0 20 | count = 0 21 | threshold = 5 22 | with open('/home/pi/lux.csv') as f: 23 | for line in f: 24 | sum += float(line) 25 | count = count + 1 26 | avg = sum/count 27 | print avg 28 | while avg <= threshold: 29 | blink(pin) 30 | -------------------------------------------------------------------------------- /envSensors/env_logger.cron.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Author: Ethan Willis, Hao Chen 3 | Description: This program will log temperature, humidity, and barometric pressure 4 | and luminosity to a log file with a given frequency. 5 | This is scheduled to run via cron jobs. An LED connected to GPIO pin 8 is turned on when the script is ran 6 | 7 | 8 | ''' 9 | 10 | import time 11 | from time import strftime 12 | import datetime 13 | import sys 14 | import RPi.GPIO as gpio 15 | 16 | ## moved this block here to turn off the LED when program starts 17 | led=8 18 | gpio.setmode(gpio.BOARD) 19 | gpio.setup(led, gpio.OUT) 20 | gpio.output(led,False) 21 | 22 | import HTU21DF 23 | import TSL2561 24 | import Adafruit_BMP.BMP085 as BMP085 25 | 26 | ''' 27 | Writes data to the logfile located at the location specified 28 | by the filename variable. 29 | ''' 30 | def write_to_log(filename, data): 31 | with open(filename, "a") as logfile: 32 | datastring = str(data[0]) + "\t" + location + "\t" + str(data[1]) + "\t" + str(data[2]) + "\t" + str(data[3]) + "\t" + str(data[4])+"\n" 33 | logfile.write(datastring) 34 | print datastring 35 | 36 | def write_lux(filename, data): 37 | with open(filename, "a") as luxfile: 38 | datastring= str(data)+"\n" 39 | luxfile.write(datastring) 40 | 41 | def readLux(): 42 | LightSensor = TSL2561.Adafruit_TSL2561() 43 | LightSensor.enableAutoGain(True) 44 | count=0 45 | luxTotal=0 46 | while True: 47 | if (count <=100): 48 | luxTotal=LightSensor.calculateLux() + luxTotal 49 | count+=1 50 | else: 51 | lux=round(luxTotal/100) 52 | break 53 | return lux 54 | 55 | def prog(filename): 56 | err=0 57 | try: 58 | print ("Reading humidity") 59 | HTU21DF.htu_reset 60 | humidity=HTU21DF.read_humidity() 61 | temp1=HTU21DF.read_temperature() 62 | time.sleep(5) 63 | except: 64 | print ("Failed") 65 | humidity="NA" 66 | temp1=0 67 | err=1 68 | try: 69 | print ("Reading the barometer") 70 | barometer = BMP085.BMP085(mode=BMP085.BMP085_ULTRAHIGHRES) 71 | pressure=barometer.read_pressure() 72 | temp2=barometer.read_temperature() 73 | time.sleep(5) 74 | except: 75 | print ("Failed") 76 | pressure="NA" 77 | temp2=0 78 | err=1 79 | if (temp1==0 or temp2==0): 80 | temp=temp1+temp2 81 | else: 82 | temp=(temp1+temp2)/2 83 | try: 84 | print ("Reading Lux level") 85 | lux=readLux() 86 | time.sleep(5) 87 | except: 88 | print ("Failed") 89 | lux="" 90 | err=1 91 | datetime=strftime("%Y-%m-%d\t%H:%M:%S") 92 | data=[datetime,temp,humidity,pressure,lux] 93 | # savenewdataentry 94 | write_to_log(filename,data) 95 | hour=strftime("%H") 96 | if int(hour) < 7: 97 | write_lux("/home/pi/lux.csv",lux) 98 | return err 99 | 100 | 101 | idfile=open("/home/pi/deviceid") 102 | location=idfile.read().strip() 103 | year=datetime.date.today().year 104 | month=datetime.date.today().month 105 | filename="/home/pi/Pies/Env/Env"+location+str(year)+"-"+str(month)+".log" 106 | err=prog(filename) 107 | if err==0: 108 | gpio.output(led,True) 109 | else: 110 | gpio.output(led,False) 111 | 112 | -------------------------------------------------------------------------------- /envSensors/images/envSensor1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/envSensors/images/envSensor1.jpg -------------------------------------------------------------------------------- /envSensors/images/envSensor2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/envSensors/images/envSensor2.jpg -------------------------------------------------------------------------------- /envSensors/images/envSensor3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/envSensors/images/envSensor3.jpg -------------------------------------------------------------------------------- /envSensors/images/envSensor4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/envSensors/images/envSensor4.jpg -------------------------------------------------------------------------------- /envSensors/images/envSensor5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/envSensors/images/envSensor5.jpg -------------------------------------------------------------------------------- /envSensors/setup_scripts/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ## NOTE: pigpoid can be found here: wget abyz.co.uk/rpi/pigpio/pigpio.zip 4 | ## need to install the following: 5 | ## enable I2C: https://learn.adafruit.com/adafruits-raspberry-pi-lesson-4-gpio-setup/configuring-i2c 6 | ## install Adafruit library for the MCP9808 https://learn.adafruit.com/mcp9808-temperature-sensor-python-library/software 7 | 8 | ## The following commands need to be run before the env log file 9 | 10 | sudo chmod 666 /sys/module/i2c_bcm2708/parameters/combined 11 | sudo echo -n 1 > /sys/module/i2c_bcm2708/parameters/combined 12 | sudo pigpiod 13 | 14 | ## Setup our DS1307 Clock 15 | ./setup_ds1307.sh 16 | -------------------------------------------------------------------------------- /envSensors/setup_scripts/setup_auto_log_copy.sh: -------------------------------------------------------------------------------- 1 | # create usb UDEV rules for running script when USB drive is plugged in. 2 | sudo echo 'SUBSYSTEMS=="usb", KERNEL=="sd[a-h]", SYMLINK+="usbkey", RUN+="/home/pi/autocopylogs.sh" SUBSYSTEMS=="usb",KERNEL=="sd[a-h]",ACTION=="remove", RUN+="/home/pi/autocopylogs.sh"' > /etc/udev/rules.d/999-env-autologging.rules 3 | sudo echo 'SUBSYSTEMS=="usb", KERNEL=="sd[a-h]1", SYMLINK+="usbkey", RUN+="/home/pi/autocopylogs.sh" SUBSYSTEMS=="usb",KERNEL=="sd[a-h]1",ACTION=="remove", RUN+="/home/pi/autocopylogs.sh"' >> /etc/udev/rules.d/999-env-autologging.rules 4 | 5 | 6 | # create shell script for copying files to usb drive from /home/pi/ 7 | OUTPUTDIR=/home/pi/autocopylogs.sh 8 | LOGFILESRC=/home/pi/behaviorRoomEnv.log 9 | LOGFILEDEST=/mnt/usblog/behaviorRoomEnv.log 10 | sudo echo '#!/bin/sh' > $OUTPUTDIR 11 | sudo echo 'ACTION=$(expr "ACTION" : "\([a-zA-Z]\+\).*")' >> $OUTPUTDIR 12 | sudo echo 'if [ "$ACTION" = "add" ]' >> $OUTPUTDIR 13 | sudo echo 'then' >> $OUTPUTDIR 14 | sudo echo ' mount /mnt/usb' >> $OUTPUTDIR 15 | sudo echo " # Copy log files to /mnt/usb/" >> $OUTPUTDIR 16 | sudo echo " cp $LOGFILESRC $LOGFILEDEST" >> $OUTPUTDIR 17 | sudo echo " # Blink RPi LED" >> $OUTPUTDIR 18 | sudo echo " # Turn off Default SD Card blinking mechanisms" >> $OUTPUTDIR 19 | sudo echo " echo none > /sys/class/leds/led0/trigger" >> $OUTPUTDIR 20 | sudo echo " echo 1 > /sys/class/leds/led0/brightness" >> $OUTPUTDIR 21 | sudo echo " sleep 1" >> $OUTPUTDIR 22 | sudo echo " echo 0 > /sys/class/leds/led0/brightness" >> $OUTPUTDIR 23 | sudo echo " sleep 1" >> $OUTPUTDIR 24 | sudo echo " echo 1 > /sys/class/leds/led0/brightness" >> $OUTPUTDIR 25 | sudo echo " sleep 2" >> $OUTPUTDIR 26 | sudo echo " echo 0 > /sys/class/leds/led0/brightness" >> $OUTPUTDIR 27 | sudo echo " sleep 2" >> $OUTPUTDIR 28 | sudo echo " echo 1 > /sys/class/leds/led0/brightness" >> $OUTPUTDIR 29 | sudo echo " sleep 1" >> $OUTPUTDIR 30 | sudo echo " echo 0 > /sys/class/leds/led0/brightness" >> $OUTPUTDIR 31 | sudo echo " sleep 1" >> $OUTPUTDIR 32 | sudo echo " echo 1 > /sys/class/leds/led0/brightness" >> $OUTPUTDIR 33 | sudo echo " sleep 1" >> $OUTPUTDIR 34 | sudo echo " echo 0 > /sys/class/leds/led0/brightness" >> $OUTPUTDIR 35 | sudo echo " sleep 1" >> $OUTPUTDIR 36 | sudo echo " echo 1 > /sys/class/leds/led0/brightness" >> $OUTPUTDIR 37 | sudo echo " sleep 1" >> $OUTPUTDIR 38 | sudo echo " # Turn back on normal SD card trigger for LED " >> $OUTPUTDIR 39 | sudo echo " echo mmc0 > /sys/class/leds/led0/trigger" >> $OUTPUTDIR 40 | sudo echo 'else' >> $OUTPUTDIR 41 | sudo echo ' umount /mnt/usb' >> $OUTPUTDIR 42 | sudo echo 'fi' >> $OUTPUTDIR 43 | 44 | 45 | # Create directory for mounting usb drive 46 | sudo mkdir /mnt/usblog 47 | 48 | # Add entry into fstab to automount usb devices to /mnt/usblog 49 | # TODO: Make this smarter and make it so that only one such entry exists in our fstab 50 | echo "/dev/usbkey /mnt/usblog vfat ro,noauto,user,exec 0 0" >> /etc/fstab 51 | -------------------------------------------------------------------------------- /envSensors/setup_scripts/setup_ds1307.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ## This script is meant to be run once in order to setup a connected ds1307 adafruit RTC module. 4 | 5 | # Step 1: Add the RTC-DS1307 to our list of modules 6 | echo "rtc-ds1307" >> /etc/modules 7 | 8 | # Step 2: Create our ds-1307 as a device on Raspberry Pi boot 9 | # TODO: Make sure that this gets echoed before the exit 0 command in rc.local 10 | echo "echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device" >> /etc/rc.local 11 | echo "sudo hwclock -s" >> /etc/rc.local 12 | -------------------------------------------------------------------------------- /extinction/ExtinctionBoxWiring.ods: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/extinction/ExtinctionBoxWiring.ods -------------------------------------------------------------------------------- /extinction/Readme.md: -------------------------------------------------------------------------------- 1 | # Using a Raspberry Pi to run extinction sessions 2 | 3 | We have several old operant chamber where the electronics are starting to fail. This project uses a RPi to record the number of licks on two spouts. There is also a constantly flashing visual cue during the session. We now use these to run the contextual extinction sessions as described in our earlier papers by Wang et al. (2014) and by Wang et al. (2014) .  4 | 5 | The *extinctionCase* holds the RPi. The *extinctionCueLightPlate* holds the cue light for one side. The *extinctionCueLightBox* is inserted into the *extinctionCase* and holds the other set of cue lights. The *extinctionCaseCover* has an opening for an LCD, which displays session info and data. 6 | 7 | The device is running either from a 5V DC microusb power supply or using a large 5V cell phone backup battery. 8 | -------------------------------------------------------------------------------- /extinction/cuelights.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import RPi.GPIO as gpio 4 | import time 5 | 6 | # BEGIN CONSTANT DEFINITIONS 7 | LED1 = int(33) 8 | LED2 = int(29) 9 | duration=int(1) 10 | 11 | # setup GPIO 12 | gpio.setwarnings(False) 13 | gpio.setmode(gpio.BOARD) 14 | gpio.setup(LED1, gpio.OUT) 15 | gpio.setup(LED2, gpio.OUT) 16 | 17 | start=time.time() 18 | 19 | while ( time.time()-start < 3600 ): 20 | gpio.output(LED1, gpio.HIGH) 21 | gpio.output(LED2, gpio.HIGH) 22 | time.sleep(duration) 23 | gpio.output(LED1, gpio.LOW) 24 | gpio.output(LED2, gpio.LOW) 25 | time.sleep(duration) 26 | 27 | -------------------------------------------------------------------------------- /extinction/extinction.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import RPi.GPIO as gpio 4 | import time 5 | import os 6 | import sys 7 | import Adafruit_MPR121.MPR121 as MPR121 8 | import Adafruit_CharLCD as LCD 9 | 10 | def initLCD(): 11 | # Raspberry Pi pin configuration: 12 | lcd_rs = 25 13 | lcd_en = 24 14 | lcd_d4 = 23 15 | lcd_d5 = 17 16 | lcd_d6 = 21 17 | lcd_d7 = 22 18 | lcd_backlight = 4 19 | # Define LCD column and row size for 16x2 LCD. 20 | lcd_columns = 16 21 | lcd_rows = 2 22 | # Initialize the LCD using the pins above. 23 | lcd = LCD.Adafruit_CharLCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7, lcd_columns, lcd_rows, lcd_backlight) 24 | lcd.clear() 25 | sysTime= time.strftime("%H:%M:%S", time.localtime()) 26 | lcd.message("Hurry up, Wifi!\n" + deviceid + "Sess."+ sessionid) 27 | return lcd 28 | 29 | def initTouch(): 30 | cap = MPR121.MPR121() 31 | if not cap.begin(): 32 | print ("Error initializing MPR121. Check your wiring!") 33 | lcd.clean() 34 | lcd.message("Touch Sensor \nConnection Error") 35 | sys.exit(1) 36 | print ("Touch Sensor Started\n") 37 | return cap 38 | 39 | def updatelcd(active, inactive, seconds): 40 | minutes=str(int(seconds/60)) 41 | lcd.clear() 42 | lcd.message("A:" + str(active) + " I:" + str(inactive) + "\n" + "Min:" + str(minutes) + " "+ deviceid[3:] + "S" +sessionid ) 43 | 44 | def recordLicks(sessionLength): 45 | active=0 46 | inactive=0 47 | start=time.time() 48 | updateTime=start 49 | print ("session started\n") 50 | while time.time() - start < sessionLength: 51 | time.sleep(0.07) # sets time resolution 52 | lapsed = time.time() - start 53 | if cap.is_touched(1): 54 | active+=1 55 | updatelcd(active, inactive, lapsed) 56 | updateTime=time.time() 57 | print(active, inactive, lapsed) 58 | with open(lickDataFile,"a") as f: 59 | f.write(str(deviceid) + "\t" + "ratID\t"+today +"\t" + startTime + "\t" + "active\t" + str(lapsed) + "\n") 60 | f.close() 61 | elif cap.is_touched(0): 62 | inactive+=1 63 | lapsed=time.time()-start 64 | updatelcd(active, inactive, lapsed) 65 | updateTime=time.time() 66 | print (active, inactive, lapsed) 67 | with open(lickDataFile,"a") as f: 68 | f.write(str(deviceid) + "\t" + "ratID\t"+today +"\t" + startTime + "\t" + "inactive\t" + str(lapsed) + "\n") 69 | f.close() 70 | if time.time() - updateTime > 60 : # update LCD every 60 sec 71 | updatelcd(active, inactive, lapsed) 72 | updateTime=time.time() 73 | # finishing the data files 74 | updatelcd(active, inactive, lapsed) 75 | print (active, inactive, lapsed) 76 | 77 | if __name__ == '__main__': 78 | idfile=open('/home/pi/deviceid') 79 | deviceid=idfile.read() 80 | deviceid=deviceid.strip() 81 | with open ("/home/pi/sessionid", "r+") as f: 82 | sessionid=f.read() 83 | sessionid=sessionid.strip() 84 | nextSession=int(sessionid)+1 85 | f.seek(0) 86 | f.write(str(nextSession)) 87 | f.close() 88 | lcd=initLCD() 89 | time.sleep(1) 90 | os.system("bash /home/pi/openbehavior/wifi-network/deviceinfo.sh") 91 | os.system("bash /home/pi/openbehavior/wifi-network/wlan0down.sh") 92 | os.system("python /home/pi/openbehavior/extinction/cuelights.py &") 93 | today= time.strftime("%Y-%m-%d", time.localtime()) 94 | startTime= time.strftime("%H:%M:%S", time.localtime()) 95 | lcd.clear() 96 | lcd.message("Session started\n" + startTime) 97 | cap=initTouch() 98 | currentTime=today + "_" + startTime 99 | lickDataFile="/home/pi/Pies/Extinction/" + deviceid + "S"+ sessionid + "_" + today + ".csv" 100 | with open(lickDataFile,"a") as f: 101 | f.write("#Session Started on " + currentTime + "\n") 102 | f.write("device\tRatID\tDate\tStartTime\tSpout\tlapsed\n") 103 | f.close() 104 | recordLicks(3600) # session length in seconds 105 | with open(lickDataFile,"a") as f: 106 | f.write("#Session Ended on " +time.strftime("%Y-%m-%d\t%H:%M:%S\t", time.localtime())+"\n") 107 | f.close() 108 | os.system('/home/pi/openbehavior/wifi-network/rsync.sh &') 109 | 110 | -------------------------------------------------------------------------------- /extinction/extinctionCase.scad: -------------------------------------------------------------------------------- 1 | $fn=100; 2 | 3 | module mounting_m25(innR=1.6, h=10){ // screw 4 | difference(){ 5 | color("orange") cylinder(r=3.8, h); 6 | cylinder(r=innR, h=10); 7 | } 8 | } 9 | 10 | module mounting_pi(){ 11 | translate([-58/2,-49/2,0]) mounting_m25(h=5); 12 | translate([58/2,-49/2,0]) mounting_m25(h=5); 13 | translate([-58/2,49/2,0]) mounting_m25(h=5); 14 | translate([58/2,49/2,0]) mounting_m25(h=5); 15 | translate([-10,0,0]) cube([85,56,0.1], center=true); // pi 16 | } 17 | 18 | 19 | module mounting(){ 20 | cube([14,12,3],center=true); 21 | } 22 | 23 | module col2nd(){ 24 | difference(){ 25 | cube([6,6,12], center=true); 26 | screw(); 27 | } 28 | } 29 | 30 | 31 | module lcd(){ // model: HD44780 32 | translate([0,0, 13.1]) cube([71.5, 25, 8.4], center=true); 33 | //translate([0,0, 13.1-3.7]) cube([80.6, 36, 0.1], center=true); // base plate 34 | } 35 | 36 | 37 | module cover(){ 38 | difference() { 39 | union(){ 40 | cube([x0,y0,3], center=true); 41 | translate([14,2,0])rotate([0,0,90]) lcd_mounting(); 42 | } 43 | rotate([0,0,180]) translate([0,0,-20]) color("blue") screw4(); 44 | # translate([13,2,15]) rotate([0,180,90])lcd(); 45 | } 46 | } 47 | 48 | 49 | module col(){ 50 | cube([8,8,12],center=true); 51 | } 52 | 53 | module col4(){ 54 | zz=15; 55 | translate([x0/2-4, y0/2-9, zz]) col(); 56 | translate([-x0/2+5, y0/2-9, zz]) col(); 57 | translate([x0/2-5, -y0/2+5, zz]) col(); 58 | translate([-x0/2+5, -y0/2+5, zz]) col(); 59 | } 60 | 61 | module screw() { 62 | translate([0,0,-10]) cylinder(r=1.6, h=20); 63 | } 64 | 65 | module screw4(){ 66 | zz=15; 67 | translate([x0/2-5, y0/2-9, zz]) screw(); 68 | translate([-x0/2+5, y0/2-9, zz]) screw(); 69 | translate([x0/2-5, -y0/2+5, zz]) screw(); 70 | translate([-x0/2+5, -y0/2+5, zz]) screw(); 71 | } 72 | 73 | x0=76; 74 | y0=104; 75 | z0=42; 76 | 77 | module case(){ 78 | difference(){ 79 | cube([x0, y0, z0], center=true); // outside 80 | translate([0,0,4]) cube([x0-4, y0-4, z0+5], center=true); // inside 81 | translate([0,y0/2,1]) cube([56, 8, 41], center=true); 82 | translate([0,-40,21]) rotate([90,0,0]) cylinder(r=3,h=30); // cables 83 | translate([-4,-53,-z0/2+5]) cube([20,10, 5], center=true); // sdcard slot 84 | translate([-25,-44,14]) rotate([90,0,0]) cylinder (r=1.5, h=20); // touch sensor 85 | # translate([3,-44,14]) rotate([90,0,0]) cylinder (r=1.5, h=20); // touch sensor 86 | translate([30,21,8]) cube ([10,10,13]); // potential meter for lcd 87 | translate([30,-45,-16])cube([20,14,8]); //powercord 88 | translate([-40, -45, -16]) cube([5,2,20]); // peak slit for the Pi LEDs, 89 | translate([-40, -49, -16]) cube([5,2,20]); // peak slit for the Pi LEDs, 90 | } 91 | translate([-4,-17,-z0/2+1]) rotate([0, 0, -90]) mounting_pi(); 92 | // translate([-25,-47,14]) rotate([90,0,0]) mounting_touch(); 93 | difference(){ 94 | col4(); 95 | screw4(); 96 | } 97 | } 98 | 99 | 100 | 101 | module lcd_mounting(){ 102 | w=75; 103 | l=31; 104 | difference(){ 105 | union(){ 106 | translate([w/2, l/2,0])cylinder(r=3.4, h=7); 107 | translate([w/2, -l/2,0])cylinder(r=3.4, h=7); 108 | translate([-w/2, -l/2,0])cylinder(r=3.4, h=7); 109 | translate([-w/2, l/2,0])cylinder(r=3.4, h=7); 110 | 111 | } 112 | union (){ 113 | translate([w/2, l/2,0])cylinder(r=1.2, h=11); 114 | translate([w/2, -l/2,0])cylinder(r=1.2, h=11); 115 | translate([-w/2, -l/2,0])cylinder(r=1.2, h=11); 116 | translate([-w/2, l/2,0])cylinder(r=1.2, h=11); 117 | } 118 | } 119 | 120 | } 121 | 122 | module mounting_touch(){ 123 | mounting_m25(innR=1.2, h=4); 124 | translate([28,0,0]) mounting_m25(innR=1.5, h=4); 125 | } 126 | 127 | //case(); 128 | translate([0,0,25]) rotate([0,180,180]) cover(); 129 | -------------------------------------------------------------------------------- /extinction/extinctionLEDBox.scad: -------------------------------------------------------------------------------- 1 | $fn=100; 2 | 3 | module LEDBoxPos() { 4 | translate([0,-2/2,0]) cube([63.4, 2,40], center=true) ; //backplate 5 | translate([0,-2/2-4.5,0]) cube([63.4, 2,40], center=true) ;//bbackplate 6 | translate([0,-25,0]) cube([77.4, 2,40], center=true); //faceplete 7 | translate([0,-25/2,0]) cube([55.4,25,40], center=true); // outside 8 | } 9 | 10 | module LEDBoxNeg() { 11 | translate([0,-25/2+2, 0]) cube([52, 26, 35.5], center=true); // inside 12 | } 13 | 14 | module drillholes() {//all four screw holes for LED board 15 | translate([4,3,0]) hollow(); 16 | translate([44,3,0]) hollow(); 17 | translate([4,26,0]) hollow(); 18 | translate([44,26,0]) hollow(); 19 | } 20 | 21 | module hollow() { //the screw holes 22 | cylinder(9.1,1.5,1.5); 23 | } 24 | 25 | module cols4LED(){ //all four inside columns 26 | translate([4,3,2.23]) column(); 27 | translate([44,3,2.23]) column(); 28 | translate([4,26,2.23]) column(); 29 | translate([44,26,2.23]) column(); 30 | } 31 | 32 | module column(){ 33 | cylinder(r=4,6); 34 | } //the inside column 35 | 36 | module led() { // hole for the LED lights 37 | cube([22,10,6],center=true); 38 | } 39 | 40 | module CueLightBox() { 41 | difference() { 42 | LEDBoxPos(); 43 | difference() { 44 | LEDBoxNeg(); 45 | rotate([90,0,0]) translate([-24,-15,17]) cols4LED(); 46 | } 47 | rotate([90,0,0]) translate([-24,-15,14]) drillholes(); 48 | translate([0,-25,12.5]) led(); 49 | } 50 | } 51 | 52 | module CueLightPanel() { 53 | difference(){ 54 | union(){ 55 | translate([0,-25,0]) cube([77.4, 2,40], center=true); //faceplete 56 | rotate([90,0,0]) translate([-24,-15,17]) cols4LED(); 57 | } 58 | rotate([90,0,0]) translate([-24,-15,16]) drillholes(); 59 | translate([0,-25,12.5]) led(); 60 | } 61 | } 62 | //translate([0,48,1]) rotate([0,0,180] ) CueLightBox(); 63 | translate([0,48,1]) rotate([0,0,180] ) CueLightPanel(); 64 | 65 | -------------------------------------------------------------------------------- /infrared/MiceTunnels/DuralLayerPCBForIRDetections.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/infrared/MiceTunnels/DuralLayerPCBForIRDetections.jpg -------------------------------------------------------------------------------- /infrared/MiceTunnels/OneWayDoorClosed.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/infrared/MiceTunnels/OneWayDoorClosed.jpg -------------------------------------------------------------------------------- /infrared/MiceTunnels/OneWayDoorOpen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/infrared/MiceTunnels/OneWayDoorOpen.jpg -------------------------------------------------------------------------------- /infrared/MiceTunnels/SixTunnelsForMiceWithOneWayDoors.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/infrared/MiceTunnels/SixTunnelsForMiceWithOneWayDoors.jpg -------------------------------------------------------------------------------- /infrared/board/ir.GBO: -------------------------------------------------------------------------------- 1 | G75* 2 | %MOIN*% 3 | %OFA0B0*% 4 | %FSLAX24Y24*% 5 | %IPPOS*% 6 | %LPD*% 7 | %AMOC8* 8 | 5,1,8,0,0,1.08239X$1,22.5* 9 | % 10 | M02* 11 | -------------------------------------------------------------------------------- /infrared/board/ir.GBS: -------------------------------------------------------------------------------- 1 | G75* 2 | %MOIN*% 3 | %OFA0B0*% 4 | %FSLAX24Y24*% 5 | %IPPOS*% 6 | %LPD*% 7 | %AMOC8* 8 | 5,1,8,0,0,1.08239X$1,22.5* 9 | % 10 | %ADD10C,0.0820*% 11 | %ADD11C,0.1360*% 12 | %ADD12OC8,0.0680*% 13 | D10* 14 | X011100Y004600D03* 15 | X014100Y004600D03* 16 | X017100Y009600D03* 17 | X013850Y012100D03* 18 | X012850Y012100D03* 19 | X011850Y012100D03* 20 | X011350Y013100D03* 21 | X012350Y013100D03* 22 | X013350Y013100D03* 23 | X017100Y012600D03* 24 | X020850Y013100D03* 25 | X021850Y013100D03* 26 | X022850Y013100D03* 27 | X022350Y012100D03* 28 | X021350Y012100D03* 29 | X023350Y012100D03* 30 | X026600Y012600D03* 31 | X026600Y009600D03* 32 | X030850Y012100D03* 33 | X031850Y012100D03* 34 | X032850Y012100D03* 35 | X032350Y013100D03* 36 | X031350Y013100D03* 37 | X030350Y013100D03* 38 | X030100Y017100D03* 39 | X033100Y017100D03* 40 | X036100Y012600D03* 41 | X036100Y009600D03* 42 | X033100Y004600D03* 43 | X030100Y004600D03* 44 | X023600Y004600D03* 45 | X020600Y004600D03* 46 | X020600Y017100D03* 47 | X023600Y017100D03* 48 | X026600Y021600D03* 49 | X026600Y024600D03* 50 | X023350Y024600D03* 51 | X022350Y024600D03* 52 | X021350Y024600D03* 53 | X020850Y025600D03* 54 | X021850Y025600D03* 55 | X022850Y025600D03* 56 | X017100Y024600D03* 57 | X013850Y024600D03* 58 | X012850Y024600D03* 59 | X011850Y024600D03* 60 | X011350Y025600D03* 61 | X012350Y025600D03* 62 | X013350Y025600D03* 63 | X017100Y021600D03* 64 | X014100Y017100D03* 65 | X011100Y017100D03* 66 | X030350Y025600D03* 67 | X031350Y025600D03* 68 | X032350Y025600D03* 69 | X031850Y024600D03* 70 | X030850Y024600D03* 71 | X032850Y024600D03* 72 | X036100Y024600D03* 73 | X036100Y021600D03* 74 | D11* 75 | X033600Y022100D03* 76 | X029600Y022100D03* 77 | X024100Y022100D03* 78 | X020100Y022100D03* 79 | X014600Y022100D03* 80 | X010600Y022100D03* 81 | X010600Y009600D03* 82 | X014600Y009600D03* 83 | X020100Y009600D03* 84 | X024100Y009600D03* 85 | X029600Y009600D03* 86 | X033600Y009600D03* 87 | D12* 88 | X003100Y006600D03* 89 | X003100Y007600D03* 90 | X004100Y007600D03* 91 | X004100Y006600D03* 92 | X004100Y008600D03* 93 | X004100Y009600D03* 94 | X004100Y010600D03* 95 | X004100Y011600D03* 96 | X004100Y012600D03* 97 | X004100Y013600D03* 98 | X003100Y013600D03* 99 | X003100Y012600D03* 100 | X003100Y011600D03* 101 | X003100Y010600D03* 102 | X003100Y009600D03* 103 | X003100Y008600D03* 104 | X003100Y014600D03* 105 | X003100Y015600D03* 106 | X003100Y016600D03* 107 | X003100Y017600D03* 108 | X003100Y018600D03* 109 | X003100Y019600D03* 110 | X003100Y020600D03* 111 | X004100Y020600D03* 112 | X004100Y019600D03* 113 | X004100Y018600D03* 114 | X004100Y017600D03* 115 | X004100Y016600D03* 116 | X004100Y015600D03* 117 | X004100Y014600D03* 118 | X004100Y021600D03* 119 | X004100Y022600D03* 120 | X004100Y023600D03* 121 | X004100Y024600D03* 122 | X004100Y025600D03* 123 | X003100Y025600D03* 124 | X003100Y024600D03* 125 | X003100Y023600D03* 126 | X003100Y022600D03* 127 | X003100Y021600D03* 128 | M02* 129 | -------------------------------------------------------------------------------- /infrared/board/ir.GTS: -------------------------------------------------------------------------------- 1 | G75* 2 | %MOIN*% 3 | %OFA0B0*% 4 | %FSLAX24Y24*% 5 | %IPPOS*% 6 | %LPD*% 7 | %AMOC8* 8 | 5,1,8,0,0,1.08239X$1,22.5* 9 | % 10 | %ADD10C,0.0820*% 11 | %ADD11C,0.1360*% 12 | %ADD12OC8,0.0680*% 13 | D10* 14 | X011100Y004600D03* 15 | X014100Y004600D03* 16 | X017100Y009600D03* 17 | X013850Y012100D03* 18 | X012850Y012100D03* 19 | X011850Y012100D03* 20 | X011350Y013100D03* 21 | X012350Y013100D03* 22 | X013350Y013100D03* 23 | X017100Y012600D03* 24 | X020850Y013100D03* 25 | X021850Y013100D03* 26 | X022850Y013100D03* 27 | X022350Y012100D03* 28 | X021350Y012100D03* 29 | X023350Y012100D03* 30 | X026600Y012600D03* 31 | X026600Y009600D03* 32 | X030850Y012100D03* 33 | X031850Y012100D03* 34 | X032850Y012100D03* 35 | X032350Y013100D03* 36 | X031350Y013100D03* 37 | X030350Y013100D03* 38 | X030100Y017100D03* 39 | X033100Y017100D03* 40 | X036100Y012600D03* 41 | X036100Y009600D03* 42 | X033100Y004600D03* 43 | X030100Y004600D03* 44 | X023600Y004600D03* 45 | X020600Y004600D03* 46 | X020600Y017100D03* 47 | X023600Y017100D03* 48 | X026600Y021600D03* 49 | X026600Y024600D03* 50 | X023350Y024600D03* 51 | X022350Y024600D03* 52 | X021350Y024600D03* 53 | X020850Y025600D03* 54 | X021850Y025600D03* 55 | X022850Y025600D03* 56 | X017100Y024600D03* 57 | X013850Y024600D03* 58 | X012850Y024600D03* 59 | X011850Y024600D03* 60 | X011350Y025600D03* 61 | X012350Y025600D03* 62 | X013350Y025600D03* 63 | X017100Y021600D03* 64 | X014100Y017100D03* 65 | X011100Y017100D03* 66 | X030350Y025600D03* 67 | X031350Y025600D03* 68 | X032350Y025600D03* 69 | X031850Y024600D03* 70 | X030850Y024600D03* 71 | X032850Y024600D03* 72 | X036100Y024600D03* 73 | X036100Y021600D03* 74 | D11* 75 | X033600Y022100D03* 76 | X029600Y022100D03* 77 | X024100Y022100D03* 78 | X020100Y022100D03* 79 | X014600Y022100D03* 80 | X010600Y022100D03* 81 | X010600Y009600D03* 82 | X014600Y009600D03* 83 | X020100Y009600D03* 84 | X024100Y009600D03* 85 | X029600Y009600D03* 86 | X033600Y009600D03* 87 | D12* 88 | X003100Y006600D03* 89 | X003100Y007600D03* 90 | X004100Y007600D03* 91 | X004100Y006600D03* 92 | X004100Y008600D03* 93 | X004100Y009600D03* 94 | X004100Y010600D03* 95 | X004100Y011600D03* 96 | X004100Y012600D03* 97 | X004100Y013600D03* 98 | X003100Y013600D03* 99 | X003100Y012600D03* 100 | X003100Y011600D03* 101 | X003100Y010600D03* 102 | X003100Y009600D03* 103 | X003100Y008600D03* 104 | X003100Y014600D03* 105 | X003100Y015600D03* 106 | X003100Y016600D03* 107 | X003100Y017600D03* 108 | X003100Y018600D03* 109 | X003100Y019600D03* 110 | X003100Y020600D03* 111 | X004100Y020600D03* 112 | X004100Y019600D03* 113 | X004100Y018600D03* 114 | X004100Y017600D03* 115 | X004100Y016600D03* 116 | X004100Y015600D03* 117 | X004100Y014600D03* 118 | X004100Y021600D03* 119 | X004100Y022600D03* 120 | X004100Y023600D03* 121 | X004100Y024600D03* 122 | X004100Y025600D03* 123 | X003100Y025600D03* 124 | X003100Y024600D03* 125 | X003100Y023600D03* 126 | X003100Y022600D03* 127 | X003100Y021600D03* 128 | M02* 129 | -------------------------------------------------------------------------------- /infrared/board/ir.TXT: -------------------------------------------------------------------------------- 1 | % 2 | M48 3 | M72 4 | T01C0.0354 5 | T02C0.0400 6 | T03C0.1280 7 | % 8 | T01 9 | X11100Y4600 10 | X14100Y4600 11 | X17100Y9600 12 | X17100Y12600 13 | X14100Y17100 14 | X11100Y17100 15 | X17100Y21600 16 | X17100Y24600 17 | X20600Y17100 18 | X23600Y17100 19 | X26600Y12600 20 | X26600Y9600 21 | X23600Y4600 22 | X20600Y4600 23 | X30100Y4600 24 | X33100Y4600 25 | X36100Y9600 26 | X36100Y12600 27 | X33100Y17100 28 | X30100Y17100 29 | X26600Y21600 30 | X26600Y24600 31 | X36100Y24600 32 | X36100Y21600 33 | T02 34 | X3100Y6600 35 | X3100Y7600 36 | X4100Y7600 37 | X4100Y6600 38 | X4100Y8600 39 | X4100Y9600 40 | X4100Y10600 41 | X4100Y11600 42 | X4100Y12600 43 | X4100Y13600 44 | X3100Y13600 45 | X3100Y12600 46 | X3100Y11600 47 | X3100Y10600 48 | X3100Y9600 49 | X3100Y8600 50 | X3100Y14600 51 | X3100Y15600 52 | X3100Y16600 53 | X3100Y17600 54 | X3100Y18600 55 | X3100Y19600 56 | X3100Y20600 57 | X4100Y20600 58 | X4100Y19600 59 | X4100Y18600 60 | X4100Y17600 61 | X4100Y16600 62 | X4100Y15600 63 | X4100Y14600 64 | X11350Y13100 65 | X12350Y13100 66 | X13350Y13100 67 | X12850Y12100 68 | X11850Y12100 69 | X13850Y12100 70 | X20850Y13100 71 | X21850Y13100 72 | X22850Y13100 73 | X22350Y12100 74 | X21350Y12100 75 | X23350Y12100 76 | X30350Y13100 77 | X31350Y13100 78 | X32350Y13100 79 | X31850Y12100 80 | X30850Y12100 81 | X32850Y12100 82 | X32850Y24600 83 | X31850Y24600 84 | X30850Y24600 85 | X30350Y25600 86 | X31350Y25600 87 | X32350Y25600 88 | X23350Y24600 89 | X22350Y24600 90 | X21350Y24600 91 | X20850Y25600 92 | X21850Y25600 93 | X22850Y25600 94 | X13850Y24600 95 | X12850Y24600 96 | X11850Y24600 97 | X11350Y25600 98 | X12350Y25600 99 | X13350Y25600 100 | X4100Y25600 101 | X4100Y24600 102 | X4100Y23600 103 | X4100Y22600 104 | X4100Y21600 105 | X3100Y21600 106 | X3100Y22600 107 | X3100Y23600 108 | X3100Y24600 109 | X3100Y25600 110 | T03 111 | X10600Y22100 112 | X14600Y22100 113 | X20100Y22100 114 | X24100Y22100 115 | X29600Y22100 116 | X33600Y22100 117 | X33600Y9600 118 | X29600Y9600 119 | X24100Y9600 120 | X20100Y9600 121 | X14600Y9600 122 | X10600Y9600 123 | M30 124 | -------------------------------------------------------------------------------- /infrared/board/ir.dri: -------------------------------------------------------------------------------- 1 | Generated by EAGLE CAM Processor 7.1.0 2 | 3 | Drill Station Info File: /Users/paper_ziggurat/Documents/eagle/IR/ir.dri 4 | 5 | Date : 9/25/14 3:31 PM 6 | Drills : generated 7 | Device : Excellon drill station 8 | 9 | Parameter settings: 10 | 11 | Tolerance Drill + : 0.00 % 12 | Tolerance Drill - : 0.00 % 13 | Rotate : no 14 | Mirror : no 15 | Optimize : yes 16 | Auto fit : yes 17 | OffsetX : 0inch 18 | OffsetY : 0inch 19 | Layers : Drills Holes 20 | 21 | Drill File Info: 22 | 23 | Data Mode : Absolute 24 | Units : 1/10000 Inch 25 | 26 | Drills used: 27 | 28 | Code Size used 29 | 30 | T01 0.0354inch 24 31 | T02 0.0400inch 76 32 | T03 0.1280inch 12 33 | 34 | Total number of drills: 112 35 | 36 | Plotfiles: 37 | 38 | /Users/paper_ziggurat/Documents/eagle/IR/ir.TXT 39 | -------------------------------------------------------------------------------- /infrared/board/ir.dru: -------------------------------------------------------------------------------- 1 | description[de] = EAGLE Design Rules\n
\nDie Standard-Design-Rules sind so gewählt, dass sie für \ndie meisten Anwendungen passen. Sollte ihre Platine \nbesondere Anforderungen haben, treffen Sie die erforderlichen\nEinstellungen hier und speichern die Design Rules unter \neinem neuen Namen ab. 2 | description[en] = EAGLE Design Rules\n
\nThe default Design Rules have been set to cover\na wide range of applications. Your particular design\nmay have different requirements, so please make the\nnecessary adjustments and save your customized\ndesign rules under a new name.
3 | layerSetup = (1*16)
4 | mtCopper = 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm
5 | mtIsolate = 1.5mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm
6 | mdWireWire = 8mil
7 | mdWirePad = 8mil
8 | mdWireVia = 8mil
9 | mdPadPad = 8mil
10 | mdPadVia = 8mil
11 | mdViaVia = 8mil
12 | mdSmdPad = 8mil
13 | mdSmdVia = 8mil
14 | mdSmdSmd = 8mil
15 | mdViaViaSameLayer = 8mil
16 | mnLayersViaInSmd = 2
17 | mdCopperDimension = 40mil
18 | mdDrill = 8mil
19 | mdSmdStop = 0mil
20 | msWidth = 10mil
21 | msDrill = 24mil
22 | msMicroVia = 9.99mm
23 | msBlindViaRatio = 0.500000
24 | rvPadTop = 0.250000
25 | rvPadInner = 0.250000
26 | rvPadBottom = 0.250000
27 | rvViaOuter = 0.250000
28 | rvViaInner = 0.250000
29 | rvMicroViaOuter = 0.250000
30 | rvMicroViaInner = 0.250000
31 | rlMinPadTop = 10mil
32 | rlMaxPadTop = 20mil
33 | rlMinPadInner = 10mil
34 | rlMaxPadInner = 20mil
35 | rlMinPadBottom = 10mil
36 | rlMaxPadBottom = 20mil
37 | rlMinViaOuter = 8mil
38 | rlMaxViaOuter = 20mil
39 | rlMinViaInner = 8mil
40 | rlMaxViaInner = 20mil
41 | rlMinMicroViaOuter = 4mil
42 | rlMaxMicroViaOuter = 20mil
43 | rlMinMicroViaInner = 4mil
44 | rlMaxMicroViaInner = 20mil
45 | psTop = -1
46 | psBottom = -1
47 | psFirst = -1
48 | psElongationLong = 100
49 | psElongationOffset = 100
50 | mvStopFrame = 1.000000
51 | mvCreamFrame = 0.000000
52 | mlMinStopFrame = 4mil
53 | mlMaxStopFrame = 4mil
54 | mlMinCreamFrame = 0mil
55 | mlMaxCreamFrame = 0mil
56 | mlViaStopLimit = 0mil
57 | srRoundness = 0.000000
58 | srMinRoundness = 0mil
59 | srMaxRoundness = 0mil
60 | slThermalIsolate = 10mil
61 | slThermalsForVias = 0
62 | dpMaxLengthDifference = 10mm
63 | dpGapFactor = 2.500000
64 | checkGrid = 0
65 | checkAngle = 0
66 | checkFont = 1
67 | checkRestrict = 1
68 | useDiameter = 13
69 | maxErrors = 50
70 |
--------------------------------------------------------------------------------
/infrared/board/ir.gpi:
--------------------------------------------------------------------------------
1 | Generated by EAGLE CAM Processor 7.1.0
2 |
3 | Photoplotter Info File: /Users/paper_ziggurat/Documents/eagle/IR/ir.gpi
4 |
5 | Date : 9/25/14 3:31 PM
6 | Plotfile : /Users/paper_ziggurat/Documents/eagle/IR/ir.GBS
7 | Apertures : generated:
8 | Device : Gerber RS-274-X photoplotter, coordinate format 2.4 inch
9 |
10 | Parameter settings:
11 |
12 | Emulate Apertures : no
13 | Tolerance Draw + : 0.00 %
14 | Tolerance Draw - : 0.00 %
15 | Tolerance Flash + : 0.00 %
16 | Tolerance Flash - : 0.00 %
17 | Rotate : no
18 | Mirror : no
19 | Optimize : yes
20 | Auto fit : yes
21 | OffsetX : 0inch
22 | OffsetY : 0inch
23 |
24 | Plotfile Info:
25 |
26 | Coordinate Format : 2.4
27 | Coordinate Units : Inch
28 | Data Mode : Absolute
29 | Zero Suppression : None
30 | End Of Block : *
31 |
32 | Apertures used:
33 |
34 | Code Shape Size used
35 |
36 | D10 round 0.0820inch 60
37 | D11 round 0.1360inch 12
38 | D12 octagon 0.0680inch 40
39 |
40 |
--------------------------------------------------------------------------------
/infrared/board/ir.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/infrared/board/ir.pdf
--------------------------------------------------------------------------------
/infrared/gpio.ir.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | import RPi.GPIO as GPIO
4 | from time import strftime
5 | import time
6 | import os
7 | import grp
8 | import pwd
9 | #from collections import defaultdict
10 |
11 | GPIO.setwarnings(False)
12 | GPIO.setmode(GPIO.BOARD)
13 |
14 | pinCount = input("Enter number of pins in use by IR sensors: ")
15 | channels = []
16 | pin_alloc = 0
17 |
18 | #get pins to be used from command line
19 | while pin_alloc < pinCount:
20 | pin = input("Enter GPIO pin number: ")
21 | if pin in range (1,27) and not pin in [1, 2, 4, 6, 9, 14, 17, 20, 25]:
22 | channels.append(pin)
23 | pin_alloc += 1
24 | else:
25 | print "Invalid GPIO pin number (power pins are included)"
26 |
27 | #initialize counts
28 | for c in channels:
29 | print str(c)
30 | GPIO.setup(c, GPIO.IN, pull_up_down = GPIO.PUD_UP)
31 |
32 | fo = open("/home/pi/data/ir_log.txt", "a")
33 | uid = pwd.getpwnam("pi").pw_uid
34 | gid = grp.getgrnam("pi").gr_gid
35 | path = "/home/pi/data/ir_log.txt"
36 | os.chown(path, uid, gid)
37 |
38 | def intervalCounting(channel):
39 | fo = open("/home/pi/data/ir_log.txt", "a")
40 | currentTime = strftime("%Y-%m-%d\t%H:%M:%S")
41 | if GPIO.input(channel):
42 | fo.write(str(currentTime) + "\tchannel " + str(channel) + "\tblocked\n")
43 | print currentTime + "\tchannel " + str(channel) + "\tblocked\n"
44 | else:
45 | fo.write(currentTime + "\tchannel " + str(channel) + "\topen\n")
46 | print currentTime + "\tchannel " + str(channel) + "\topen\n"
47 | return
48 |
49 | for c in channels:
50 | GPIO.add_event_detect(c, GPIO.RISING, callback = intervalCounting, bouncetime = 0)
51 |
52 | try:
53 | while True:
54 | time.sleep(50)
55 |
56 | except KeyboardInterrupt:
57 | GPIO.cleanup()
58 |
59 | GPIO.cleanup()
60 |
--------------------------------------------------------------------------------
/infrared/parts_list.txt:
--------------------------------------------------------------------------------
1 | items from sparkfun.
2 |
3 | Infrared Emitter & Detector Set:
4 | SEN-00241
5 |
6 | Emitter:
7 | LTE-302
8 |
9 | Detector:
10 | LTR-301
11 |
12 |
--------------------------------------------------------------------------------
/motion/Readme.md:
--------------------------------------------------------------------------------
1 | #Adding motion sensors to operant conditioning chambers
2 |
3 | ## Description
4 | This project adds a motion sensor to the commercial MedPC operant chambers. The motion sensor is controlled by a RPi. The RPi is powered by the 28V power source available in the operant chamber (via a step down converter). The RPi is turned on and off via MedPC programs. The data are stored in the SD card of the Pi. Each operant chamber use one Pi. All the Pi computers are connected by a WiFi network and data are transferred to a remote server via sftp.
5 |
6 | ## Parts list
7 |
8 | Molex connector for 28V. Mfg P/N: 03-06-2032 [Mouser] ( http://www.mouser.com/ProductDetail/Molex/03-06-2032/?qs=%2fha2pyFadugvI%2fznVBilJA6N4bQxmqBpdBoCzb%2f9bbY%3d)
9 |
10 | Molex pin. Mfg P/N: 02-06-2103 [Mouser] (http://www.mouser.com/ProductDetail/Molex/02-06-2103/?qs=%2fha2pyFaduhC0HER4S2%2flGJ0%2fQN3qzJ5F27g%252bKWL4TY%3d)
11 |
12 | Motion sensor. [Amazon] (http://www.amazon.com/gp/product/B00FDPO9B8)
13 |
14 | EdiMax WiFi USB. [Amazon] (http://www.amazon.com/gp/product/B003MTTJOY)
15 |
16 | Step-down LM2596 power converter. [eBay] (http://www.ebay.com/itm/161476280982)
17 |
18 | ## Notes
19 |
20 | Two step down DC-DC converters are used. One is set to 5 V to power the RPi. This is always on. The other one is set to 3.3 V. This is only on when the output port in the MedPC is activated. This then controls the on and off of the motion.py program.
21 |
22 |
--------------------------------------------------------------------------------
/motion/motion.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python2
2 |
3 | import RPi.GPIO as gpio
4 | import time
5 | import os
6 | import sys
7 |
8 | pirPin=12
9 | offPin=16
10 | motionLed=40
11 | gpio.setwarnings(False)
12 | gpio.setmode(gpio.BOARD)
13 | gpio.setup(pirPin, gpio.IN, pull_up_down=gpio.PUD_DOWN)
14 | gpio.setup(offPin, gpio.IN, pull_up_down=gpio.PUD_DOWN)
15 | gpio.setup(motionLed, gpio.OUT)
16 |
17 | while(True):
18 | if not gpio.input(offPin):
19 | os.system("/home/pi/openbehavior/wifi-network/killhtpd.sh &") # kills htpd in 30 sec
20 | os.system("/home/pi/openbehavior/wifi-network/deviceinfo.sh") # try to connect to wifi but only wait for max 20 sec.
21 | os.system("sudo ifconfig wlan0 down") # disconnect from the internet
22 | boxid=open("/home/pi/deviceid").read().strip()
23 | # session id
24 | with open ("/home/pi/sessionid", "r+") as f:
25 | storedSessionID=f.read().strip()
26 | sessionID=int(storedSessionID)+1
27 | f.seek(0)
28 | f.write(str(sessionID))
29 | f.close()
30 | startTime=time.strftime("%Y-%m-%d_%H:%M:%S", time.localtime())
31 | motionDataFile='/home/pi/Pies/OCMotion/'+ boxid + "_s" + str(sessionID) + "_" + startTime + ".csv"
32 | with open(motionDataFile,"a") as f:
33 | f.write("#Session started at " + startTime +"\n")
34 | f.write("seconds\n")
35 | f.close()
36 | print ("session starts at " + startTime)
37 | cnt=0
38 | start=time.time()
39 |
40 | while gpio.input(offPin)==0:
41 | # time.sleep(0.1) # time resolution of motion data
42 | if gpio.input(pirPin):
43 | cnt=cnt+1
44 | # print ("motion cnt " + str(cnt))
45 | with open(motionDataFile,"a") as f:
46 | lapsed=time.time()-start
47 | f.write(str(lapsed) +"\n")
48 | f.close()
49 | gpio.output(motionLed, True)
50 | time.sleep(0.2)
51 | gpio.output(motionLed, False)
52 | time.sleep(0.2)
53 | # print "session ended\n"
54 | with open(motionDataFile,"a") as f:
55 | f.write("#Session ended\t" + boxid + "\tsession"+ str(sessionid)+ "\t"+ time.strftime("%Y-%m-%d\t%H:%M:%S", time.localtime()) + "\t" + str(cnt)+"\n")
56 | f.close()
57 | os.system("sudo ifconfig wlan0 up")
58 | os.system("/home/pi/openbehavior/wifi-network/rsync.sh &")
59 | else:
60 | time.sleep(1)
61 | gpio.output(motionLed, True)
62 | #print "pin 16 has no signal\n"
63 |
64 |
--------------------------------------------------------------------------------
/motion/motionSensorCaseOperantChamber.scad:
--------------------------------------------------------------------------------
1 | $fn=100;
2 |
3 | module mounting_m25(innR=1.6, h=10){ // screw
4 | difference(){
5 | color("orange") cylinder(r=3.8, h);
6 | cylinder(r=innR, h=10);
7 | }
8 | }
9 |
10 | module mounting_pi(){
11 | translate([-58/2,-49/2,0]) mounting_m25();
12 | translate([58/2,-49/2,0]) mounting_m25();
13 | translate([-58/2,49/2,0]) mounting_m25();
14 | translate([58/2,49/2,0]) mounting_m25();
15 | translate([-10,0,0]) cube([85,56,0.1], center=true);
16 | }
17 |
18 | module volhouse () { /* voltage converter*/
19 | difference(){
20 | cube([22,27,12],center=true);
21 | cube([18,23,12.1],center=true);
22 | }
23 | }
24 | module mounting(){
25 | cube([14,12,3],center=true);
26 | }
27 |
28 | module col2nd(){
29 | difference(){
30 | cube([6,6,12], center=true);
31 | screw();
32 | }
33 | }
34 | module cover(){
35 | difference() {
36 | cube([x0,y0,3], center=true);
37 | rotate([0,0,180]) translate([0,0,-20]) color("blue") screw4();
38 | }
39 | y=-20;
40 | x=16;
41 | z=4.5;
42 | translate([x,y,z]) volhouse();
43 | translate([-x,y,z]) volhouse();
44 | translate([x+13,y, z]) col2nd();
45 | translate([-x-13,y, z]) col2nd();
46 | }
47 |
48 |
49 | module col(){
50 | cube([8,8,12],center=true);
51 | }
52 | module col4(){
53 | zz=15;
54 | translate([x0/2-4, y0/2-9, zz]) col();
55 | translate([-x0/2+5, y0/2-9, zz]) col();
56 | translate([x0/2-5, -y0/2+5, zz]) col();
57 | translate([-x0/2+5, -y0/2+5, zz]) col();
58 |
59 | }
60 |
61 | module screw() {
62 | translate([0,0,-10]) cylinder(r=1.6, h=20);
63 | }
64 |
65 |
66 | module screw4(){
67 | zz=15;
68 | translate([x0/2-5, y0/2-9, zz]) screw();
69 | translate([-x0/2+5, y0/2-9, zz]) screw();
70 | translate([x0/2-5, -y0/2+5, zz]) screw();
71 | translate([-x0/2+5, -y0/2+5, zz]) screw();
72 | }
73 |
74 | x0=76;
75 | y0=104;
76 | z0=42;
77 |
78 |
79 | module case(){
80 | difference(){
81 | cube([x0, y0, z0], center=true); // outside
82 | translate([0,0,4]) cube([x0-4, y0-4, z0+5], center=true); // inside
83 | translate([0,y0/2,1]) cube([56, 8, 41], center=true);
84 | translate([0,-40,21]) rotate([90,0,0]) cylinder(r=3,h=30); // power cords
85 | translate([-4,-53,-z0/2+10]) cube([20,10, 5], center=true); // sdcard slot
86 | }
87 | translate([-4,-17,-z0/2+1]) rotate([0, 0, -90]) mounting_pi();
88 | difference(){
89 | col4();
90 | screw4();
91 | }
92 | }
93 |
94 | module volcover(){
95 | sx=29;
96 | sy=-20;
97 | sz=10;
98 | difference(){
99 | translate([0, sy,sz]) cube([64,8,2],center=true);
100 | translate([sx, sy,sz])screw();
101 | translate([-sx, sy,sz])screw();
102 | }
103 | }
104 |
105 | module motionBoxPos() {
106 | translate([0,-2/2,0]) cube([63.4, 2,40], center=true) ; //backplate
107 | translate([0,-2/2-4.5,0]) cube([63.4, 2,40], center=true) ;//bbackplate
108 | translate([0,-25,0]) cube([77.4, 2,40], center=true); //faceplete
109 | translate([0,-25/2,0]) cube([55.4,25,40], center=true); // outside
110 | }
111 |
112 | module motionBoxNeg() {
113 | translate([0,-25/2+2, 0]) cube([51.4, 26, 31], center=true); // inside
114 | translate([14.5,0,0]) rotate([90,0,0]) cylinder(r=1, h=25); // motion sensor mounting screw
115 | translate([-14.5, 0,0]) rotate([90,0,0]) cylinder(r=1, h=25); // motion sensor mounting screw
116 | rotate([90,0,0]) cylinder(r=4.5, h=30); // motion sensor proper
117 | translate([0,-25,0])rotate([90,0,0]) cylinder(r1=4.5, r2=14,h=3); // motion sensor proper
118 | }
119 |
120 | module motionBoardBox(){
121 | difference() {
122 | motionBoxPos();
123 | motionBoxNeg();
124 | }
125 | }
126 |
127 | //case();
128 | //translate([0,48,1]) rotate([0,0,180] ) motionBoardBox();
129 | //translate([0,0,25]) rotate([0,180,180]) cover();
130 | color("yellow") volcover();
131 |
132 |
--------------------------------------------------------------------------------
/openscad/pump_design/middlePieceModified.scad:
--------------------------------------------------------------------------------
1 | pumpHolderWidth=50.25;
2 | pumpHolderHeight=36;//38.26;
3 | pumpHolderThickness=10.20;
4 |
5 |
6 | semiCircleDiameter=19; //16.36;
7 | semiCircleRadius=semiCircleDiameter/2;
8 |
9 | semiCircleHeight=26.54;
10 | semiCircleThickness=7.23;
11 |
12 | recBlockHeight=13.63;
13 | recBlockWidth=8.25;
14 |
15 | offsetThickness=2.03;
16 |
17 |
18 |
19 | sideScrewRadius=1.75;
20 | sideScrewHeight=4;
21 | sideScrewOffsetRatio=0.38;
22 |
23 | rotate([90,0,0]) scale([0.94,1,1]) translate([0,0,0]) difference(){
24 | minkowski(){
25 |
26 | difference(){
27 | difference(){
28 | difference(){
29 | cube([pumpHolderWidth,pumpHolderThickness,pumpHolderHeight],center=true);
30 |
31 | translate([0,(pumpHolderThickness/2)-(semiCircleThickness/2)+.001,(pumpHolderHeight/2) - (semiCircleHeight/2) + .5]) color("red") union(){
32 | rotate([90,0,0]) cylinder(h=pumpHolderThickness+5,r=semiCircleRadius, center=true);
33 |
34 | color("blue") translate([0,0,(semiCircleHeight/2)/2]) cube([semiCircleDiameter,pumpHolderThickness+5,semiCircleHeight/2 +.1],center=true);
35 | }
36 | }
37 |
38 | union(){
39 | color("red") translate([(pumpHolderWidth/2)-(recBlockWidth/2),0,-(pumpHolderHeight/2)+(recBlockHeight/2)]) cube([recBlockWidth,pumpHolderThickness,recBlockHeight],center=true);
40 |
41 | color("red") translate([-((pumpHolderWidth/2)-(recBlockWidth/2)),0,-(pumpHolderHeight/2)+(recBlockHeight/2)]) cube([recBlockWidth,pumpHolderThickness,recBlockHeight],center=true);
42 | }
43 |
44 | }
45 |
46 | translate([0,(pumpHolderThickness/2)-(offsetThickness/2),(pumpHolderHeight-recBlockHeight)/2 - ((pumpHolderHeight/2) - recBlockHeight)]) color("black") cube([pumpHolderWidth-3,offsetThickness,pumpHolderHeight-recBlockHeight],center=true);
47 |
48 | }
49 |
50 |
51 | cylinder(1,center=true,$fn=50);
52 |
53 | }
54 | union(){
55 | screwZAxisoffSet=2.15;
56 | color("red") translate([pumpHolderWidth/2 - (recBlockWidth/2) - (sideScrewHeight/2)-3.1,0,(pumpHolderHeight/2) + 1/2 -(pumpHolderHeight-recBlockHeight) - (sideScrewOffsetRatio*recBlockHeight) - screwZAxisoffSet]) rotate([0,90,0]) cylinder(h=sideScrewHeight,r=sideScrewRadius,$fn=50,center=true);
57 |
58 | color("red") translate([-(pumpHolderWidth/2 - (recBlockWidth/2) - (sideScrewHeight/2)-3.1 ),0,(pumpHolderHeight/2) + 1/2 -(pumpHolderHeight-recBlockHeight) - (sideScrewOffsetRatio*recBlockHeight) - screwZAxisoffSet]) rotate([0,90,0]) cylinder(h=sideScrewHeight,r=sideScrewRadius,$fn=50,center=true);
59 | }
60 | }
61 |
62 |
63 |
64 | //
65 | ////pumpHolderWidth
66 | ////recBlockWidth/2 + (sideScrewHeight/2)
67 | //color("red") translate([pumpHolderWidth/2 - (recBlockWidth/2) - (sideScrewHeight/2)-3.1,0,(pumpHolderHeight/2) + 1/2 -(pumpHolderHeight-recBlockHeight) - (sideScrewOffsetRatio*recBlockHeight)]) rotate([0,90,0]) cylinder(h=sideScrewHeight,r=sideScrewRadius,$fn=50,center=true);
68 | //
69 | //color("red") translate([-(pumpHolderWidth/2 - (recBlockWidth/2) - (sideScrewHeight/2)-3.1 ),0,(pumpHolderHeight/2) + 1/2 -(pumpHolderHeight-recBlockHeight) - (sideScrewOffsetRatio*recBlockHeight)]) rotate([0,90,0]) cylinder(h=sideScrewHeight,r=sideScrewRadius,$fn=50,center=true);
70 | ////cube([60,1,1],center=true);
71 | //
72 | //
73 | //color("blue") translate([0,0,recBlockHeight/2]) cube([recBlockWidth, pumpHolderThickness,recBlockHeight],center=true);
74 | //minkowski(){
75 | // translate([0,0,recBlockHeight/2]) cube([recBlockWidth, pumpHolderThickness,recBlockHeight],center=true);
76 | // cylinder(.00000000001,center=true,$fn=50);
77 | //}
78 |
79 |
80 |
81 | //-----------------------------------------
82 |
83 | //translate([0,(pumpHolderThickness/2)-(offsetThickness/2),(pumpHolderHeight-recBlockHeight)/2 - ((pumpHolderHeight/2) - recBlockHeight)]) color("black") cube([pumpHolderWidth-3,offsetThickness,pumpHolderHeight-recBlockHeight],center=true);
84 |
85 | //
86 | //difference(){
87 | // %cube([pumpHolderWidth,pumpHolderThickness,pumpHolderHeight],center=true);
88 | //
89 | // translate([0,(pumpHolderThickness/2)-(semiCircleThickness/2)+.001,(pumpHolderHeight/2) - (semiCircleHeight/2)]) color("red") union(){
90 | // rotate([90,0,0]) cylinder(h=pumpHolderThickness+5,r=semiCircleRadius, center=true);
91 | //
92 | // color("red") translate([0,0,(semiCircleHeight/2)/2]) cube([semiCircleDiameter,pumpHolderThickness+5,semiCircleHeight/2 +.1],center=true);
93 | // }
94 | //}
--------------------------------------------------------------------------------
/operantLeverPressing/1video.h264:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/operantLeverPressing/1video.h264
--------------------------------------------------------------------------------
/operantLeverPressing/2video.h264:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/operantLeverPressing/2video.h264
--------------------------------------------------------------------------------
/operantLeverPressing/Readme.md:
--------------------------------------------------------------------------------
1 | #Operant Lever Pressing
2 |
3 | This is one of the earliest attempts we had. It uses a RPi to monitor two levers (i.e. switches). The output is a dry food pellet deliverying device.
4 |
--------------------------------------------------------------------------------
/operantLeverPressing/bmp183.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/operantLeverPressing/bmp183.pyc
--------------------------------------------------------------------------------
/operantLeverPressing/htu21d.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chen42/openbehavior/f2d94cf2dc8312ae9e5fc149849a6ac7abaee278/operantLeverPressing/htu21d.pyc
--------------------------------------------------------------------------------
/operantLeverPressing/leverRecord.py:
--------------------------------------------------------------------------------
1 | import RPi.GPIO as GPIO
2 | import time
3 | from time import gmtime, strftime
4 | import sys
5 |
6 | # the pin numbers where the two levers ar connected
7 | l1=8
8 | l2=10
9 |
10 | def init():
11 | GPIO.setmode(GPIO.BOARD)
12 | GPIO.setwarnings(False)
13 | GPIO.setup(l1, GPIO.IN) #for lever 1
14 | GPIO.setup(l2, GPIO.IN) #for lever 2
15 |
16 | def main(argv):
17 | c1=0 # counter for number of presses on lever 1
18 | c2=0 # counter for number of presses on lever 2
19 | t1, animalID = argv.split(":")
20 | t = float(t1)
21 | totalT = time.time() + t - .5 #it should end a bit early than our main program
22 | while True:
23 | input1= GPIO.input(l1)
24 | input2= GPIO.input(l2)
25 | if(input1==0): # i.e. lever is pressed
26 | curTime = strftime("%Y-%m-%d %H:%M:%S", gmtime())
27 | c1+=1
28 | data = open('data.csv', 'a')
29 | data.write(animalID + "," + str(curTime) + ",Lever 1\n")
30 | data.close()
31 | time.sleep(.200) # debouncing
32 | if(input2==0):
33 | c2+=1
34 | curTime = strftime("%Y-%m-%d %H:%M:%S", gmtime())
35 | data = open('data.csv', 'a')
36 | data.write(animalID + "," + str(curTime) + ",Lever 2\n")
37 | time.sleep(.200)
38 | if(time.time()>totalT):
39 | print(c1,":",c2)
40 | break
41 |
42 |
43 | if __name__ == "__main__":
44 | init()
45 | main(sys.argv[1])
46 |
--------------------------------------------------------------------------------
/operantLeverPressing/measure.py:
--------------------------------------------------------------------------------
1 | '''
2 | bmp183 - Adafruit BMP183 SPI interface for Raspberry Pi
3 | Copyright (C) 2014 Przemo Firszt @ https://github.com/PrzemoF/bmp183
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see